{
  "openapi": "3.1.0",
  "info": {
    "title": "FulfillPros API",
    "version": "1.0.0",
    "summary": "Orders, fulfillment, items, inventory and ship nodes for brands and 3PLs.",
    "contact": {
      "name": "FulfillPros support",
      "email": "support@fulfillpros.ai",
      "url": "https://fulfillpros.ai/support"
    },
    "termsOfService": "https://fulfillpros.ai/legal/terms",
    "license": {
      "name": "Proprietary",
      "url": "https://fulfillpros.ai/legal/terms"
    },
    "description": "The API behind the FulfillPros portal, for connecting your own systems: an order\nmanagement system sending orders, a 3PL's WMS accepting and shipping them, an ERP keeping\nitem catalogs and stock in step.\n\n## Getting started\n\n1. **Sign in** with the email and password you use at\n   [app.fulfillpros.ai](https://app.fulfillpros.ai): `POST /api/v1/auth/login`. The response\n   carries an `accessToken`.\n2. **Create an API key** with that token: `POST /api/v1/api-keys` with\n   `Authorization: Bearer <accessToken>`. The key (`fpk_…`) is shown once. Store it as a\n   secret.\n3. **Call the API with the key** in the `X-API-Key` header. Check it with\n   `GET /api/v1/me`.\n\nTo try requests from this page, click **Authorize** and paste the key. Requests go to\nproduction with that key.\n\n## Authentication\n\nSend **one** of:\n\n| Header | Use | Lifetime |\n|---|---|---|\n| `X-API-Key: fpk_…` | Server-to-server integrations. | Until revoked, or `expiresInDays`. |\n| `Authorization: Bearer <accessToken>` | Short sessions, and to create your first key. | 24 hours; renew with `POST /api/v1/auth/refresh`. |\n\nDon't send both. An invalid bearer token cancels a valid key on the same request.\n\nA key acts as the account that created it, with that account's role (`BRAND` or\n`THREE_PL`) and permissions. It can call everything the account can in the portal.\n\n**Missing or invalid credentials return `403`, not `401`,** usually with an empty body.\n\n## Mutating requests need an `Idempotency-Key`\n\nEvery `POST` and `PATCH` needs an `Idempotency-Key` header (login and refresh excepted).\nWithout it you get `400 MISSING_IDEMPOTENCY_KEY`.\n\n- Use a fresh UUID for each new operation, and reuse it only to retry that same operation.\n- A retry with a key that already completed gets the **original response replayed** for\n  24 hours, including `4xx` responses. A retry while the first attempt is still running\n  gets `409 IDEMPOTENCY_CONFLICT`.\n- Keys are **global**, not scoped to your account or the endpoint. A key reused for a\n  different request returns the first request's response. Always use UUIDs.\n- `PUT` and `DELETE` don't take the header.\n\n## Responses\n\nSuccessful responses are wrapped in an envelope:\n\n```json\n{ \"success\": true, \"data\": { … }, \"requestId\": null, \"traceId\": null, \"timestamp\": \"2026-09-18T20:15:00Z\" }\n```\n\nThe operation descriptions below describe `data`. Exceptions: `204` responses have no body.\n\nErrors use this body:\n\n```json\n{ \"code\": \"VALIDATION_ERROR\", \"message\": \"Request validation failed\", \"requestId\": null, \"traceId\": null, \"details\": { \"itemId\": \"must not be blank\" } }\n```\n\nSome `403`, `404` and `409` responses have an **empty body**. Rely on the status code.\nSend an `X-Request-ID` header of your own and it's echoed back as `requestId` in error\nbodies, which helps when you contact support.\n\n## Pagination\n\nList endpoints take `page` (0-based) and `size`. Two response shapes exist:\n\n- **Orders** return `content`, `page`, `size`, `totalElements`, `totalPages`, `hasNext`.\n- **Everything else** returns `content`, `number` (the page), `size`, `totalElements`,\n  `totalPages`, `first`, `last`, plus Spring's `pageable` and `sort` objects, which you can\n  ignore.\n\n## Limits\n\n1,000 requests per second per IP address. Beyond that, requests get `503` from the edge.\nRequest bodies are limited to 10 MB, and CSV uploads to 1 MB.\n\n## Conventions\n\n- JSON field names are camelCase, except ship nodes, which use snake_case.\n- Timestamps are ISO-8601 in UTC. Dates are `yyyy-MM-dd`.\n- Money is in integer cents (`orderValueCents`, `unitPriceCents`).\n- Nulls are sent, not omitted. Unknown request fields are ignored.\n"
  },
  "servers": [
    {
      "url": "https://app.fulfillpros.ai",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    },
    {
      "BearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Authentication",
      "description": "Sign in and renew access tokens."
    },
    {
      "name": "API keys",
      "description": "Create and revoke the keys your integrations use. Requires the `account.api_keys`\npermission.\n"
    },
    {
      "name": "Account",
      "description": "Who the current credentials belong to."
    },
    {
      "name": "Orders",
      "description": "Create and track orders. A brand sees its own orders. A 3PL sees orders with at least\none fulfillment request assigned to it, and within them only its own requests.\nRequires the `ops.orders` permission.\n"
    },
    {
      "name": "Fulfillment",
      "description": "Accept, reject, progress and ship a fulfillment request: the part of an order routed to\none warehouse. Called by the 3PL the request is assigned to, or by a brand for requests\nit fulfills from its own warehouse. Requires the `ops.fulfillment` permission.\n"
    },
    {
      "name": "Items",
      "description": "A brand's item catalog. Items are keyed by brand, item code (`itemId`) and unit of\nmeasure (`uom`, default `EACH`). Sales-channel variants link to an item when the item's\ncode equals the variant's SKU. Requires the `ops.items` permission.\n"
    },
    {
      "name": "Inventory",
      "description": "Stock levels per item and ship node. Requires the `ops.inventory` permission.\n"
    },
    {
      "name": "Ship nodes",
      "description": "Warehouses, stores and pop-up locations that stock and ship orders. Brands and 3PLs use\nthe same endpoints and see the nodes they own. Requires the `ops.ship_nodes`\npermission.\n"
    },
    {
      "name": "Sales channels",
      "description": "The stores and integrations orders come from, their product catalogs, and pushing stock\nback to them. Requires the `ops.channels` permission (`ops.inventory` for the inventory\nupload).\n"
    }
  ],
  "paths": {
    "/api/v1/auth/login": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "operationId": "login",
        "summary": "Sign in",
        "description": "Exchanges an email and password for an access token (24 hours) and a refresh token\n(30 days). Accounts that sign in only with email links have no password and get\n`INVALID_CREDENTIALS`. Set one in the portal first.\n\nDoesn't need an `Idempotency-Key`.\n",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LoginRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Signed in.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LoginEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_CREDENTIALS` for an unknown email, a wrong password or a passwordless\naccount; `VALIDATION_ERROR` for a malformed request.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is pending approval, rejected or suspended.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth/refresh": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "operationId": "refreshAccessToken",
        "summary": "Renew an access token",
        "description": "Returns a new access token. The refresh token itself is not rotated. Keep using it\nuntil it expires.\n\nDoesn't need an `Idempotency-Key`.\n",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "refreshToken"
                ],
                "properties": {
                  "refreshToken": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A new access token.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "accessToken": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_REFRESH_TOKEN`: missing, unknown, expired or revoked.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The account is pending approval, rejected or suspended.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys": {
      "post": {
        "tags": [
          "API keys"
        ],
        "operationId": "createApiKey",
        "summary": "Create an API key",
        "description": "The key acts as your account, with your account's role. **The raw key is returned\nonly in this response.** Only a hash is stored.\n\nA retry with the same `Idempotency-Key` within 24 hours replays this response,\nincluding the key, so treat that header value as sensitive too.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateApiKeyRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ApiKeyCreated"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "get": {
        "tags": [
          "API keys"
        ],
        "operationId": "listApiKeys",
        "summary": "List API keys",
        "description": "Your account's keys, newest first, including revoked ones (`isActive` false).",
        "responses": {
          "200": {
            "description": "The keys.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ApiKeySummary"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/api-keys/{id}": {
      "delete": {
        "tags": [
          "API keys"
        ],
        "operationId": "revokeApiKey",
        "summary": "Revoke an API key",
        "description": "Takes effect immediately. Revoking a revoked key is a no-op.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Revoked. No body."
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No key with that id in your account. Empty body."
          }
        }
      }
    },
    "/api/v1/me": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getMe",
        "summary": "Who am I",
        "description": "The user and account behind the current credentials, and what they may do. A cheap\nway to check that a key works.\n",
        "responses": {
          "200": {
            "description": "The current principal.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Me"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/orders": {
      "get": {
        "tags": [
          "Orders"
        ],
        "operationId": "listOrders",
        "summary": "List orders",
        "description": "Newest first. A brand gets its orders. A 3PL gets orders with at least one\nfulfillment request assigned to it, with `fulfillmentRequests` narrowed to its own.\n`lineItems` always lists the whole order.\n\nTakes paging only; there are no filters. `statusHistory` is null here. Fetch a single\norder for its history.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "name": "size",
            "in": "query",
            "description": "Page size.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of orders.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/OrderPage"
                            },
                            {
                              "type": "object",
                              "properties": {
                                "content": {
                                  "type": "array",
                                  "items": {
                                    "$ref": "#/components/schemas/Order"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Orders"
        ],
        "operationId": "createOrder",
        "summary": "Create an order",
        "description": "Brands only. The order is created in `RECEIVED` and routed to a warehouse\nasynchronously. Poll `GET /api/v1/orders/{id}` to see where it went.\n\n`channelId` must be one of your sales channels. For orders from your own system,\ncreate a channel of type `API` once (`POST /api/v1/brands/channels`) and use its id.\n\nIf forced sourcing (`forcedOwnerType` and related fields) names a warehouse you can't\nroute to, the order is still created, in status `HELD` with a `holdReason`, and is not\nrouted until you fix it with `PATCH /api/v1/orders/{orderId}/line-items/{lineItemId}`.\n\n**Idempotency:** the same `Idempotency-Key` always returns the same order with `201`,\neven after the 24-hour replay window. `externalOrderId` must also be unique per brand.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrderRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created (or the order an earlier request with this key created).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "`channelId` is missing or unknown. This body is the success envelope with\n`data: null`, not an error body. `MISSING_IDEMPOTENCY_KEY` and malformed JSON use\nthe error body.\n",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "$ref": "#/components/schemas/Error"
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "Not a brand, or the channel belongs to another brand. Empty body."
          },
          "502": {
            "description": "The channel couldn't be verified. Retry with the same `Idempotency-Key`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/orders/{id}": {
      "get": {
        "tags": [
          "Orders"
        ],
        "operationId": "getOrder",
        "summary": "Get an order",
        "description": "The full order: fulfillment requests with warehouse, tracking and carrier, and\n`statusHistory`, newest first. A 3PL sees only its own fulfillment requests.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Not your order. Empty body."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/orders/by-external-id/{externalOrderId}": {
      "get": {
        "tags": [
          "Orders"
        ],
        "operationId": "getOrderByExternalId",
        "summary": "Find an order by your own order id",
        "description": "Brands only: looks up `externalOrderId` among your orders. The response has\n`fulfillmentRequests: []` and no history. Follow up with `GET /api/v1/orders/{id}`\nfor those.\n",
        "parameters": [
          {
            "name": "externalOrderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/orders/{id}/cancel": {
      "post": {
        "tags": [
          "Orders"
        ],
        "operationId": "cancelOrder",
        "summary": "Cancel an order",
        "description": "Brands only, for their own orders. Cancels the order and every fulfillment request\nnot yet being processed. An order that is already processing, shipped, delivered,\ncancelled or returned can't be cancelled.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "description": "Recorded on the order's history."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelled. `fulfillmentRequests` is empty in this response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "description": "Not your order, or not a brand. Empty body."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/InvalidTransition"
          }
        }
      }
    },
    "/api/v1/orders/{id}/reroute": {
      "post": {
        "tags": [
          "Orders"
        ],
        "operationId": "rerouteOrder",
        "summary": "Route an order again",
        "description": "Brands only. Retries routing for an order in `RECEIVED` or `EXCEPTION`, for example\nafter adding stock. From `EXCEPTION`, warehouses that rejected it become eligible\nagain. No request body.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "Routing restarted. `fulfillmentRequests` is empty in this response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "The order is not in `RECEIVED` or `EXCEPTION` (`BAD_REQUEST`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Not your order. Empty body."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/orders/{orderId}/line-items/{lineItemId}": {
      "patch": {
        "tags": [
          "Orders"
        ],
        "operationId": "updateOrderLineItem",
        "summary": "Update a line item",
        "description": "Brands only. Sets a line's `externalOrderLineRef`, and, with\n`updateForcedSourcing: true`, where it must ship from. Sourcing can only change while\nthe order is `RECEIVED` or `HELD`. A `HELD` order goes back to `RECEIVED` once its\nsourcing is valid.\n\n`externalOrderLineRef` is always written: omit it and it's cleared. Send the current\nvalue to keep it.\n",
        "parameters": [
          {
            "name": "orderId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lineItemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLineItemRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "description": "Not your order. Empty body."
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/orders/{orderId}/fulfillment-requests/{requestId}/status": {
      "post": {
        "tags": [
          "Fulfillment"
        ],
        "operationId": "updateFulfillmentStatus",
        "summary": "Move a fulfillment request to a new status",
        "description": "The main call for a warehouse: accept, start processing, ship, deliver, or raise an\nexception. The order's own status is recomputed from its requests.\n\nAllowed moves (anything else returns `422`):\n\n| From | To |\n|---|---|\n| `ROUTED` | `ACCEPTED`, `SENT_TO_WMS`, `EXCEPTION`, `CANCELLED` |\n| `SENT_TO_WMS` | `ACCEPTED`, `PROCESSING`, `SHIPPED`, `EXCEPTION`, `CANCELLED` |\n| `ACCEPTED` | `PROCESSING`, `SHIPPED`, `EXCEPTION`, `CANCELLED` |\n| `PROCESSING` | `SHIPPED`, `EXCEPTION` |\n| `SHIPPED` | `DELIVERED`, `EXCEPTION`, `RETURNED` |\n| `DELIVERED` | `RETURNED` |\n\nMoving to `SHIPPED` ships everything allocated to the request, with the\n`trackingNumber` and `carrier` you send, and pushes the fulfillment to the sales\nchannel. To ship part of a request, use `…/shipments` instead.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPathForRequest"
          },
          {
            "$ref": "#/components/parameters/RequestIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFulfillmentStatusRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated. The order, with your fulfillment requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "description": "The request isn't assigned to you. Empty body."
          },
          "404": {
            "description": "No such request, or it belongs to a different order (empty body)."
          },
          "409": {
            "$ref": "#/components/responses/IdempotencyConflict"
          },
          "422": {
            "$ref": "#/components/responses/InvalidTransition"
          }
        }
      }
    },
    "/api/v1/orders/{orderId}/fulfillment-requests/{requestId}/reject": {
      "post": {
        "tags": [
          "Fulfillment"
        ],
        "operationId": "rejectFulfillmentRequest",
        "summary": "Reject a fulfillment request",
        "description": "Hands the order back for routing elsewhere, for example when the warehouse can't\nfill it. Only for a request in `ROUTED` or `SENT_TO_WMS`, on an order with a single\nfulfillment request. The request is removed, the order returns to `ROUTING`, and your\nwarehouse is skipped for it for a cool-down period.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPathForRequest"
          },
          {
            "$ref": "#/components/parameters/RequestIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Rejected. The order, now in `ROUTING`, with no fulfillment requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "description": "The request isn't assigned to you. Empty body."
          },
          "404": {
            "description": "No such request, or it belongs to a different order (empty body)."
          },
          "422": {
            "description": "The request is past `SENT_TO_WMS`, or the order has several requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/orders/{orderId}/fulfillment-requests/{requestId}/shipments": {
      "post": {
        "tags": [
          "Fulfillment"
        ],
        "operationId": "recordShipment",
        "summary": "Record a shipment (full or partial)",
        "description": "Records one parcel: which lines and quantities it carries, with its tracking number.\nCall it once per parcel. The request moves to `SHIPPED` when its shipments cover every\nallocated unit. Until then its status is unchanged. Each shipment is pushed to the\nsales channel as its own fulfillment.\n\nAn empty `lineItems`, a line not on this request, a quantity of zero or less, or more\nthan the line has left to ship is rejected. That currently comes back as\n`500 INTERNAL_ERROR`, not `400`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/OrderIdPathForRequest"
          },
          {
            "$ref": "#/components/parameters/RequestIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RecordShipmentRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recorded. `fulfillmentRequests` is empty in this response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "description": "The request isn't assigned to you. Empty body."
          },
          "404": {
            "description": "No such request, or it belongs to a different order (empty body)."
          },
          "422": {
            "$ref": "#/components/responses/InvalidTransition"
          },
          "500": {
            "description": "An invalid line or quantity (see above).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/items": {
      "get": {
        "tags": [
          "Items"
        ],
        "operationId": "listItems",
        "summary": "List a brand's items",
        "description": "Newest first; `sort` is ignored. `search` matches the item code, the title, or the\nSKU a sales channel carries for the item, case-insensitively.\n\nA 3PL can read the items of brands it has an active partnership with.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Exact and case-sensitive.",
            "schema": {
              "$ref": "#/components/schemas/ItemStatus"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Size"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of items.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/Page"
                            },
                            {
                              "type": "object",
                              "properties": {
                                "content": {
                                  "type": "array",
                                  "items": {
                                    "$ref": "#/components/schemas/Item"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Items"
        ],
        "operationId": "createItem",
        "summary": "Create an item",
        "description": "Returns `200`, not `201`. An item with the same `itemId` and `uom` already existing,\neven an inactive one, is a `409`. To create-or-update in bulk, use\n`…/items/batch`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateItemRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "An item with this `itemId` and `uom` exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/items/{itemId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/BrandIdPath"
        },
        {
          "name": "itemId",
          "in": "path",
          "required": true,
          "description": "The item code. Codes containing `/` or `%` can't be used in a path; address those\nitems by id where an `/by-id/` route exists.\n",
          "schema": {
            "type": "string"
          }
        },
        {
          "name": "uom",
          "in": "query",
          "description": "Unit of measure.",
          "schema": {
            "type": "string",
            "default": "EACH"
          }
        }
      ],
      "get": {
        "tags": [
          "Items"
        ],
        "operationId": "getItem",
        "summary": "Get an item by its code",
        "description": "`channelSkus` and `channelLinks` are not filled in on this endpoint. Use the list for those.",
        "responses": {
          "200": {
            "description": "The item.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemEnvelope"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "tags": [
          "Items"
        ],
        "operationId": "updateItem",
        "summary": "Update an item",
        "description": "Fields you send overwrite; fields you omit or send as `null` are left alone, so a field\ncan't be cleared. Sending `payload.uom` moves the item to that unit of measure.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "payload": {
                    "$ref": "#/components/schemas/ItemPayload"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Items"
        ],
        "operationId": "deactivateItemByCode",
        "summary": "Deactivate an item by its code",
        "description": "Sets the item's status to `Inactive`. Nothing is deleted: the item keeps its stock and\nits sales-channel links, and orders for it still route. Returns `200` with\n`data: null`.\n",
        "responses": {
          "200": {
            "description": "Deactivated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Envelope"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/items/by-id/{id}/status": {
      "patch": {
        "tags": [
          "Items"
        ],
        "operationId": "setItemStatus",
        "summary": "Activate or deactivate an item by id",
        "description": "Addresses the item by its `id`, so it works for any item code, including codes named\nafter a product title that contain `/` or `%`. Deactivating hides an item without\ndeleting it: it keeps its stock and channel links, and orders for it still route. A\nconnected WMS stops pulling stock counts for it.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "The item's `id` (not its code).",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "One of `Active`, `Draft`, `Inactive`, `Discontinued`, in any case.",
                    "examples": [
                      "Inactive"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No item with that id belongs to this brand.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/items/batch": {
      "post": {
        "tags": [
          "Items"
        ],
        "operationId": "upsertItems",
        "summary": "Create or update items in bulk",
        "description": "Creates items that don't exist and updates the ones that do, matched on `itemId` and\n`uom`. Updates apply only the fields you send. Row-level problems come back in\n`errors`, with the 1-based position of the row.\n\nA blank `itemId` anywhere in the array currently fails the whole request with `500`.\nValidate before sending.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CreateItemRequest"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Counts, and any row errors.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/BatchUpsertResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/items/upload": {
      "post": {
        "tags": [
          "Items"
        ],
        "operationId": "uploadItemsCsv",
        "summary": "Create or update items from a CSV",
        "description": "The same create-or-update as `…/items/batch`, from a CSV file of at most 1 MB.\n\n- The first line is the header. `item_id` is required; every other column is an\n  `ItemPayload` field in snake_case (`title`, `uom`, `status`, `unit_cost`, …).\n  Headers are matched loosely: `item_id`, `itemId` and `Item Id` all work.\n- Comma-separated, UTF-8, double quotes for quoting. Fields can't span lines.\n- Unknown columns are ignored; empty cells leave the field unchanged.\n- Row numbers in `errors` count the header as row 1.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "A `.csv` file."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Counts, and any row errors.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/BatchUpsertResult"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "No file, not a CSV, or no header row.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/threepl/items": {
      "get": {
        "tags": [
          "Items"
        ],
        "operationId": "listPartnerItems",
        "summary": "List items across your brands (3PL)",
        "description": "3PLs only. Items of every brand you have an active partnership with, newest first,\nwith `brandName` filled in. The same `search` and `status` filters as the per-brand\nlist. A `brandId` you don't partner with returns an empty page.\n",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "$ref": "#/components/schemas/ItemStatus"
            }
          },
          {
            "name": "brandId",
            "in": "query",
            "description": "Narrow to one brand.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Size"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of items.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/Page"
                            },
                            {
                              "type": "object",
                              "properties": {
                                "content": {
                                  "type": "array",
                                  "items": {
                                    "$ref": "#/components/schemas/Item"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/threepl/brands": {
      "get": {
        "tags": [
          "Items"
        ],
        "operationId": "listPartnerBrands",
        "summary": "List the brands you fulfill for (3PL)",
        "description": "3PLs only. Brands with an active partnership, by name.",
        "responses": {
          "200": {
            "description": "The brands.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "brandId": {
                                "type": "string"
                              },
                              "brandName": {
                                "type": "string"
                              }
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/inventory": {
      "get": {
        "tags": [
          "Inventory"
        ],
        "operationId": "listInventory",
        "summary": "List a brand's stock levels",
        "description": "One row per item and ship node, ordered by item code then ship node; `sort` is\nignored. Rows with no ship node hold stock not yet assigned to a warehouse. Each row\ncarries its item's code, title and channel SKUs, so no second lookup is needed.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "name": "search",
            "in": "query",
            "description": "Item code, title or channel SKU; case-insensitive.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "shipNodeId",
            "in": "query",
            "description": "One ship node, or `none` for stock not assigned to one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "threePlId",
            "in": "query",
            "description": "Only ship nodes this 3PL fulfills the brand from.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Size"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of stock rows.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/Page"
                            },
                            {
                              "type": "object",
                              "properties": {
                                "content": {
                                  "type": "array",
                                  "items": {
                                    "$ref": "#/components/schemas/InventoryRow"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/inventory/{brandItemId}": {
      "get": {
        "tags": [
          "Inventory"
        ],
        "operationId": "getItemInventory",
        "summary": "Get one item's stock at every ship node",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "$ref": "#/components/parameters/BrandItemIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "The item's rows, including the one with no ship node, if any.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/InventoryLevel"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No item with that id belongs to this brand.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/inventory/{brandItemId}/adjust": {
      "post": {
        "tags": [
          "Inventory"
        ],
        "operationId": "adjustInventory",
        "summary": "Adjust stock",
        "description": "Adds `delta` (negative to subtract) to one quantity of one item at one ship node, and\nrecords it in the item's adjustment log. `delta` is a change, not a new total: to\ncorrect 100 on hand to 80, send `-20`. The level row is created if it doesn't exist.\nThe change reaches connected sales channels on their next push.\n\nA result below zero is refused, currently as `500 INTERNAL_ERROR`, not `400`. So is an\n`adjustmentType` or `referenceType` outside the listed values.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "$ref": "#/components/parameters/BrandItemIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdjustInventoryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The level after the adjustment.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/InventoryLevel"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`field` is not one of the three quantities, or the request is malformed.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "No access to the brand, or the ship node can't fulfill for this brand.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No item with that id belongs to this brand.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/brands/{brandId}/inventory/{brandItemId}/log": {
      "get": {
        "tags": [
          "Inventory"
        ],
        "operationId": "getInventoryLog",
        "summary": "Get an item's adjustment history",
        "description": "Newest first.",
        "parameters": [
          {
            "$ref": "#/components/parameters/BrandIdPath"
          },
          {
            "$ref": "#/components/parameters/BrandItemIdPath"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Size"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of adjustments.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/Page"
                            },
                            {
                              "type": "object",
                              "properties": {
                                "content": {
                                  "type": "array",
                                  "items": {
                                    "$ref": "#/components/schemas/InventoryAdjustment"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/threepl/inventory": {
      "get": {
        "tags": [
          "Inventory"
        ],
        "operationId": "listPartnerInventory",
        "summary": "List stock across your brands (3PL)",
        "description": "3PLs only. Stock rows for every brand you have an active partnership with, with\n`brandName` filled in. The same filters as the per-brand list, plus `brandId`.\n",
        "parameters": [
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "brandId",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "shipNodeId",
            "in": "query",
            "description": "One ship node, or `none` for stock not assigned to one.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Size"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of stock rows.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/Page"
                            },
                            {
                              "type": "object",
                              "properties": {
                                "content": {
                                  "type": "array",
                                  "items": {
                                    "$ref": "#/components/schemas/InventoryRow"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/ship-nodes/mine": {
      "get": {
        "tags": [
          "Ship nodes"
        ],
        "operationId": "listShipNodes",
        "summary": "List your ship nodes",
        "description": "Every node your account owns, active and inactive. Not paginated.",
        "responses": {
          "200": {
            "description": "The nodes.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/ShipNode"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/ship-nodes": {
      "post": {
        "tags": [
          "Ship nodes"
        ],
        "operationId": "createShipNode",
        "summary": "Create a ship node",
        "description": "Only `description` is required. `node_type` defaults to `WAREHOUSE` and\n`activate_flag` to `Y`. Set `latitude` and `longitude`: routing uses them to pick the\nnode closest to each customer.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShipNodeRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShipNodeEnvelope"
                }
              }
            }
          },
          "400": {
            "description": "`description` is missing. Empty body."
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/ship-nodes/{id}": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string"
          }
        }
      ],
      "get": {
        "tags": [
          "Ship nodes"
        ],
        "operationId": "getShipNode",
        "summary": "Get a ship node",
        "responses": {
          "200": {
            "description": "The node. A 3PL's node also carries its fee schedule in `charges`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShipNodeEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Another account owns this node. Empty body."
          },
          "404": {
            "description": "No such node. Empty body."
          }
        }
      },
      "patch": {
        "tags": [
          "Ship nodes"
        ],
        "operationId": "updateShipNode",
        "summary": "Update a ship node",
        "description": "Only the fields you send change; a field can't be cleared to null. `capabilities`\nreplaces the whole list. Send `activate_flag: \"Y\"` to reactivate a node.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ShipNodeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ShipNodeEnvelope"
                }
              }
            }
          },
          "403": {
            "description": "Another account owns this node. Empty body."
          },
          "404": {
            "description": "No such node. Empty body."
          }
        }
      },
      "delete": {
        "tags": [
          "Ship nodes"
        ],
        "operationId": "deactivateShipNode",
        "summary": "Deactivate a ship node",
        "description": "Sets `activate_flag` to `N`; nothing is deleted. A 3PL node with active capacity\nlistings can't be deactivated (`409`).\n",
        "responses": {
          "204": {
            "description": "Deactivated. No body."
          },
          "403": {
            "description": "Another account owns this node. Empty body."
          },
          "404": {
            "description": "No such node. Empty body."
          },
          "409": {
            "description": "The node has active capacity listings. Empty body."
          }
        }
      }
    },
    "/api/v1/brands/channels": {
      "get": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "listChannels",
        "summary": "List your sales channels (brand)",
        "description": "Brands only. Your active channels.",
        "responses": {
          "200": {
            "description": "The channels.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/Channel"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "createChannel",
        "summary": "Add a sales channel (brand)",
        "description": "Brands only. Use type `API` for orders your own system sends with\n`POST /api/v1/orders`. `name` is required for every type except `SHOPIFY`.\n\nShopify stores connect through the FulfillPros Shopify app, not this endpoint:\n`SHOPIFY` returns `409` unless the store is already connected to your account, in\nwhich case it returns `200` with that channel.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateChannelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "`SHOPIFY`: the store is already connected to your account.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Channel"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Created.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/Channel"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Unsupported `type`, or `name` missing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "description": "`SHOPIFY`: connect the store through the FulfillPros Shopify app.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/threepl/channels": {
      "get": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "listPartnerChannels",
        "summary": "List your brands' sales channels (3PL)",
        "description": "3PLs only. Active channels of every brand you partner with, by name.",
        "responses": {
          "200": {
            "description": "The channels.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/PartnerChannel"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/api/v1/channels/{channelId}/products": {
      "get": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "listChannelProducts",
        "summary": "List a channel's products",
        "description": "The products FulfillPros has imported from the channel. Here `sort` is honored, for\nexample `sort=title,asc`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          },
          {
            "name": "status",
            "in": "query",
            "description": "Exact match, e.g. `active`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Size"
          },
          {
            "name": "sort",
            "in": "query",
            "description": "`property,asc|desc`, e.g. `title,asc` or `updatedAt,desc`.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "One page of products.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "allOf": [
                            {
                              "$ref": "#/components/schemas/Page"
                            },
                            {
                              "type": "object",
                              "properties": {
                                "content": {
                                  "type": "array",
                                  "items": {
                                    "$ref": "#/components/schemas/ProductSummary"
                                  }
                                }
                              }
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/channels/{channelId}/products/{productId}": {
      "get": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "getChannelProduct",
        "summary": "Get a product with its SKUs",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          },
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The product.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/ProductDetail"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "description": "No such product on this channel. Empty body."
          }
        }
      }
    },
    "/api/v1/channels/{channelId}/products/sync": {
      "post": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "startProductSync",
        "summary": "Import the channel's catalog",
        "description": "Shopify channels only. Starts importing products in the background and returns\n`202` straight away. Poll `…/products/sync/status` for the outcome. Imported variants\nbecome items, linked by SKU. See the brand setup guide on fulfillpros.ai for how that\nmatching works.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Started.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "type": "object",
                          "properties": {
                            "channelId": {
                              "type": "string"
                            },
                            "status": {
                              "type": "string",
                              "const": "started"
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Not a Shopify channel, or the store isn't connected.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/channels/{channelId}/products/sync/status": {
      "get": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "getProductSyncStatus",
        "summary": "Get the latest catalog import",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "The most recent import, or `data: null` if there has never been one.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "oneOf": [
                            {
                              "$ref": "#/components/schemas/ProductSyncJob"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/channels/{channelId}/inventory/upload": {
      "post": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "uploadChannelInventory",
        "summary": "Push stock to the channel now",
        "description": "Shopify channels only. Sends current available stock to the store's FulfillPros\nlocation right away, rather than waiting for the next scheduled push. Runs to\ncompletion before responding.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "The push that just ran.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/InventoryPushJob"
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Not a Shopify channel, the store isn't connected, or it has no FulfillPros location yet.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/v1/channels/{channelId}/inventory/upload/status": {
      "get": {
        "tags": [
          "Sales channels"
        ],
        "operationId": "getChannelInventoryPushStatus",
        "summary": "Get the latest stock push",
        "parameters": [
          {
            "$ref": "#/components/parameters/ChannelIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "The most recent push, or `data: null` if there has never been one.",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Envelope"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "data": {
                          "oneOf": [
                            {
                              "$ref": "#/components/schemas/InventoryPushJob"
                            },
                            {
                              "type": "null"
                            }
                          ]
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "An API key (`fpk_…`) from `POST /api/v1/api-keys`."
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "An `accessToken` from `POST /api/v1/auth/login`, valid for 24 hours."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "A fresh UUID per operation; reuse it only to retry the same operation.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "Page": {
        "name": "page",
        "in": "query",
        "description": "0-based page number.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "default": 0
        }
      },
      "Size": {
        "name": "size",
        "in": "query",
        "description": "Page size.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2000,
          "default": 20
        }
      },
      "BrandIdPath": {
        "name": "brandId",
        "in": "path",
        "required": true,
        "description": "The brand's id. A brand uses its own; a 3PL, a partner brand's.",
        "schema": {
          "type": "string"
        }
      },
      "BrandItemIdPath": {
        "name": "brandItemId",
        "in": "path",
        "required": true,
        "description": "The item's `id` (not its item code).",
        "schema": {
          "type": "string"
        }
      },
      "ChannelIdPath": {
        "name": "channelId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "OrderIdPath": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "The FulfillPros order id.",
        "schema": {
          "type": "string"
        }
      },
      "OrderIdPathForRequest": {
        "name": "orderId",
        "in": "path",
        "required": true,
        "description": "The FulfillPros order id.",
        "schema": {
          "type": "string"
        }
      },
      "RequestIdPath": {
        "name": "requestId",
        "in": "path",
        "required": true,
        "description": "The fulfillment request's id, from the order's `fulfillmentRequests`.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "`VALIDATION_ERROR` (see `details`), `MALFORMED_REQUEST`, `INVALID_PARAMETER`, or\n`MISSING_IDEMPOTENCY_KEY`.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Missing or invalid credentials, a role that can't call this endpoint, a permission\nyour role lacks (`ROLE_FORBIDDEN`), or a resource you have no access to. Often an\nempty body.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found (`…_NOT_FOUND` or `NOT_FOUND`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "IdempotencyConflict": {
        "description": "`IDEMPOTENCY_CONFLICT`: a request with this `Idempotency-Key` is still running.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InvalidTransition": {
        "description": "`INVALID_STATUS_TRANSITION`: the current status doesn't allow this change.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Envelope": {
        "type": "object",
        "required": [
          "success",
          "timestamp"
        ],
        "properties": {
          "success": {
            "type": "boolean"
          },
          "data": {
            "description": "The payload; see each operation."
          },
          "requestId": {
            "type": [
              "string",
              "null"
            ]
          },
          "traceId": {
            "type": [
              "string",
              "null"
            ]
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "examples": [
              "VALIDATION_ERROR"
            ]
          },
          "message": {
            "type": "string"
          },
          "requestId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Your `X-Request-ID` header, echoed."
          },
          "traceId": {
            "type": [
              "string",
              "null"
            ]
          },
          "details": {
            "type": "object",
            "description": "For `VALIDATION_ERROR`, the first problem per field.",
            "additionalProperties": {
              "type": "string"
            }
          }
        }
      },
      "Page": {
        "type": "object",
        "description": "A page of results. `pageable` and `sort` are also present and can be ignored.",
        "properties": {
          "content": {
            "type": "array",
            "items": {}
          },
          "number": {
            "type": "integer",
            "description": "0-based page number."
          },
          "size": {
            "type": "integer"
          },
          "totalElements": {
            "type": "integer",
            "format": "int64"
          },
          "totalPages": {
            "type": "integer"
          },
          "numberOfElements": {
            "type": "integer"
          },
          "first": {
            "type": "boolean"
          },
          "last": {
            "type": "boolean"
          },
          "empty": {
            "type": "boolean"
          }
        }
      },
      "OrderPage": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {}
          },
          "page": {
            "type": "integer",
            "description": "0-based page number."
          },
          "size": {
            "type": "integer"
          },
          "totalElements": {
            "type": "integer",
            "format": "int64"
          },
          "totalPages": {
            "type": "integer"
          },
          "hasNext": {
            "type": "boolean"
          }
        }
      },
      "LoginRequest": {
        "type": "object",
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "format": "password"
          }
        }
      },
      "LoginEnvelope": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "type": "object",
                "properties": {
                  "accessToken": {
                    "type": "string",
                    "description": "Valid for 24 hours."
                  },
                  "refreshToken": {
                    "type": "string",
                    "description": "Valid for 30 days."
                  },
                  "userId": {
                    "type": "string"
                  },
                  "tenantId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Your account's id (the brand or 3PL)."
                  },
                  "role": {
                    "$ref": "#/components/schemas/PrincipalRole"
                  },
                  "email": {
                    "type": "string"
                  },
                  "name": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "accountStatus": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "passwordSet": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        ]
      },
      "PrincipalRole": {
        "type": "string",
        "enum": [
          "BRAND",
          "THREE_PL",
          "ADMIN",
          "SERVICE"
        ]
      },
      "CreateApiKeyRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "examples": [
              "NetSuite order sync"
            ]
          },
          "expiresInDays": {
            "type": "integer",
            "minimum": 1,
            "description": "Omit for a key that doesn't expire."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Reserved. Stored but not enforced yet; a key can do what its account can."
          }
        }
      },
      "ApiKeyCreated": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "key": {
            "type": "string",
            "description": "The key itself, `fpk_` + 48 characters. Shown only here."
          },
          "prefix": {
            "type": "string",
            "description": "The first 8 characters, to recognize the key later."
          },
          "name": {
            "type": "string"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ApiKeySummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "$ref": "#/components/schemas/PrincipalRole"
          },
          "isActive": {
            "type": "boolean"
          },
          "lastUsedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Me": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "principalRole": {
            "$ref": "#/components/schemas/PrincipalRole"
          },
          "accountStatus": {
            "type": [
              "string",
              "null"
            ]
          },
          "account": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "BRAND",
                  "THREE_PL"
                ]
              },
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "role": {
            "type": [
              "object",
              "null"
            ],
            "description": "The role you hold in the account.",
            "properties": {
              "id": {
                "type": "string"
              },
              "key": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "owner": {
            "type": "boolean"
          },
          "platformAdmin": {
            "type": "boolean"
          },
          "permissions": {
            "type": "object",
            "description": "Every permission key, e.g. `ops.orders`, mapped to your access level.",
            "additionalProperties": {
              "type": "string",
              "enum": [
                "NONE",
                "VIEW",
                "EDIT"
              ]
            }
          },
          "availableAccounts": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string"
                },
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                }
              }
            }
          },
          "scope": {
            "type": "object",
            "description": "For 3PL team members limited to some brands or ship nodes.",
            "properties": {
              "unrestricted": {
                "type": "boolean"
              },
              "groupNames": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "OrderStatus": {
        "type": "string",
        "description": "`PARTIALLY_*` values apply to orders only, when their fulfillment requests are in\ndifferent states. `HELD` means forced sourcing needs fixing before the order routes.\n",
        "enum": [
          "RECEIVED",
          "ROUTING",
          "ROUTED",
          "SENT_TO_WMS",
          "ACCEPTED",
          "PROCESSING",
          "SHIPPED",
          "DELIVERED",
          "PARTIALLY_ACCEPTED",
          "PARTIALLY_SHIPPED",
          "PARTIALLY_DELIVERED",
          "EXCEPTION",
          "CANCELLED",
          "RETURNED",
          "HELD"
        ]
      },
      "OwnerType": {
        "type": "string",
        "enum": [
          "THREE_PL",
          "BRAND"
        ]
      },
      "OrderEnvelope": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/Order"
              }
            }
          }
        ]
      },
      "Order": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "brandId": {
            "type": "string"
          },
          "brandName": {
            "type": [
              "string",
              "null"
            ]
          },
          "channelId": {
            "type": "string"
          },
          "channelType": {
            "type": [
              "string",
              "null"
            ]
          },
          "channelName": {
            "type": [
              "string",
              "null"
            ]
          },
          "externalOrderId": {
            "type": "string",
            "description": "Your id for the order."
          },
          "status": {
            "$ref": "#/components/schemas/OrderStatus"
          },
          "shipToName": {
            "type": "string"
          },
          "shipToAddress1": {
            "type": "string"
          },
          "shipToAddress2": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipToCity": {
            "type": "string"
          },
          "shipToState": {
            "type": "string"
          },
          "shipToZip": {
            "type": "string"
          },
          "shipToCountry": {
            "type": "string"
          },
          "shipToPhone": {
            "type": [
              "string",
              "null"
            ]
          },
          "orderValueCents": {
            "type": "integer",
            "format": "int64"
          },
          "currency": {
            "type": "string"
          },
          "orderType": {
            "$ref": "#/components/schemas/OrderType"
          },
          "fulfillmentRequests": {
            "type": "array",
            "description": "Where the order is being fulfilled. Empty in some responses; see each operation.",
            "items": {
              "$ref": "#/components/schemas/FulfillmentRequest"
            }
          },
          "lineItems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderLineItem"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "statusHistory": {
            "type": [
              "array",
              "null"
            ],
            "description": "Newest first. Only `GET /api/v1/orders/{id}` fills this in.",
            "items": {
              "$ref": "#/components/schemas/StatusEvent"
            }
          },
          "lastChannelSyncAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "channelSyncError": {
            "type": [
              "string",
              "null"
            ]
          },
          "forcedOwnerType": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/OwnerType"
              },
              {
                "type": "null"
              }
            ]
          },
          "forcedThreePlId": {
            "type": [
              "string",
              "null"
            ]
          },
          "forcedShipNodeId": {
            "type": [
              "string",
              "null"
            ]
          },
          "holdReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why a `HELD` order isn't routing."
          }
        }
      },
      "OrderType": {
        "type": "string",
        "enum": [
          "DTC",
          "B2B",
          "MARKETPLACE",
          "WHOLESALE"
        ]
      },
      "OrderLineItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "orderLineItemId": {
            "type": "string",
            "description": "Same as `id`; use it in shipments."
          },
          "sku": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "integer",
            "description": "Units ordered. Inside a fulfillment request, the units allocated to it."
          },
          "unitPriceCents": {
            "type": "integer",
            "format": "int64"
          },
          "fulfillmentRequestId": {
            "type": [
              "string",
              "null"
            ]
          },
          "orderLineNumber": {
            "type": [
              "integer",
              "null"
            ]
          },
          "externalOrderLineRef": {
            "type": [
              "string",
              "null"
            ]
          },
          "derivedStatus": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/OrderStatus"
              },
              {
                "type": "null"
              }
            ]
          },
          "partial": {
            "type": "boolean"
          },
          "backorderedQuantity": {
            "type": [
              "integer",
              "null"
            ]
          },
          "cancelledQuantity": {
            "type": [
              "integer",
              "null"
            ]
          },
          "unfulfilledDisposition": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "BACKORDERED",
              "CANCELLED",
              null
            ]
          },
          "forcedOwnerType": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/OwnerType"
              },
              {
                "type": "null"
              }
            ]
          },
          "forcedThreePlId": {
            "type": [
              "string",
              "null"
            ]
          },
          "forcedShipNodeId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "FulfillmentRequest": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "requestIndex": {
            "type": "integer"
          },
          "status": {
            "$ref": "#/components/schemas/OrderStatus"
          },
          "ownerType": {
            "$ref": "#/components/schemas/OwnerType"
          },
          "threePlId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The 3PL fulfilling it, or the brand's own id when `ownerType` is `BRAND`."
          },
          "threePlName": {
            "type": [
              "string",
              "null"
            ]
          },
          "listingId": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipNodeId": {
            "type": [
              "string",
              "null"
            ]
          },
          "shipNodeName": {
            "type": [
              "string",
              "null"
            ]
          },
          "routingScore": {
            "type": [
              "number",
              "null"
            ]
          },
          "routingReason": {
            "type": [
              "string",
              "null"
            ]
          },
          "trackingNumber": {
            "type": [
              "string",
              "null"
            ]
          },
          "carrier": {
            "type": [
              "string",
              "null"
            ]
          },
          "shippedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "deliveredAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "delegationRole": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "CONTRACTED",
              "PARTNER",
              null
            ],
            "description": "When one 3PL fulfills on behalf of another. Always null for brands."
          },
          "partnerThreePlName": {
            "type": [
              "string",
              "null"
            ]
          },
          "contractedThreePlName": {
            "type": [
              "string",
              "null"
            ]
          },
          "lineItems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderLineItem"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "StatusEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "note": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "CreateOrderRequest": {
        "type": "object",
        "required": [
          "channelId",
          "externalOrderId",
          "shipToName",
          "shipToAddress1",
          "shipToCity",
          "shipToState",
          "shipToZip",
          "lineItems"
        ],
        "properties": {
          "channelId": {
            "type": "string",
            "description": "One of your sales channels."
          },
          "externalOrderId": {
            "type": "string",
            "description": "Your id for the order. Must be unique among your orders."
          },
          "externalOrderRef": {
            "type": "string",
            "description": "A free-form reference; not returned."
          },
          "shipToName": {
            "type": "string"
          },
          "shipToAddress1": {
            "type": "string"
          },
          "shipToAddress2": {
            "type": "string"
          },
          "shipToCity": {
            "type": "string"
          },
          "shipToState": {
            "type": "string",
            "description": "Two-letter state code, e.g. `OH`."
          },
          "shipToZip": {
            "type": "string"
          },
          "shipToCountry": {
            "type": "string",
            "default": "US"
          },
          "shipToPhone": {
            "type": "string"
          },
          "shipToLatitude": {
            "type": "number",
            "description": "Optional. Without it, the address is geocoded for routing."
          },
          "shipToLongitude": {
            "type": "number"
          },
          "orderValueCents": {
            "type": "integer",
            "format": "int64",
            "default": 0
          },
          "currency": {
            "type": "string",
            "default": "USD"
          },
          "orderType": {
            "allOf": [
              {
                "$ref": "#/components/schemas/OrderType"
              }
            ],
            "default": "DTC"
          },
          "forcedOwnerType": {
            "$ref": "#/components/schemas/OwnerType",
            "description": "Force where the whole order ships from: `THREE_PL` with `forcedThreePlId` (and\noptionally `forcedShipNodeId`), or `BRAND` for one of your own ship nodes.\n"
          },
          "forcedThreePlId": {
            "type": "string"
          },
          "forcedShipNodeId": {
            "type": "string"
          },
          "lineItems": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/CreateOrderLineItem"
            }
          }
        }
      },
      "CreateOrderLineItem": {
        "type": "object",
        "required": [
          "sku",
          "name",
          "quantity"
        ],
        "properties": {
          "sku": {
            "type": "string",
            "description": "Matched to an item by its code, or by a sales-channel SKU linked to it."
          },
          "name": {
            "type": "string"
          },
          "quantity": {
            "type": "integer",
            "minimum": 1
          },
          "unitPriceCents": {
            "type": "integer",
            "format": "int64"
          },
          "weightOz": {
            "type": "number"
          },
          "imageUrl": {
            "type": "string"
          },
          "externalLineItemId": {
            "type": "string"
          },
          "orderLineNumber": {
            "type": "integer",
            "description": "Defaults to the line's 1-based position."
          },
          "externalOrderLineRef": {
            "type": "string"
          },
          "forcedOwnerType": {
            "$ref": "#/components/schemas/OwnerType",
            "description": "Force this line's source; overrides the order-level setting."
          },
          "forcedThreePlId": {
            "type": "string"
          },
          "forcedShipNodeId": {
            "type": "string"
          }
        }
      },
      "UpdateLineItemRequest": {
        "type": "object",
        "properties": {
          "externalOrderLineRef": {
            "type": [
              "string",
              "null"
            ],
            "description": "Always written. Omitting it clears it."
          },
          "updateForcedSourcing": {
            "type": "boolean",
            "description": "`true` to apply the three `forced*` fields below."
          },
          "forcedOwnerType": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/OwnerType"
              },
              {
                "type": "null"
              }
            ]
          },
          "forcedThreePlId": {
            "type": [
              "string",
              "null"
            ]
          },
          "forcedShipNodeId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "UpdateFulfillmentStatusRequest": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "$ref": "#/components/schemas/OrderStatus"
          },
          "note": {
            "type": "string",
            "description": "Recorded on the order's history."
          },
          "trackingNumber": {
            "type": "string",
            "description": "Used when `status` is `SHIPPED`."
          },
          "carrier": {
            "type": "string",
            "description": "Used when `status` is `SHIPPED`, e.g. `UPS`."
          }
        }
      },
      "RecordShipmentRequest": {
        "type": "object",
        "required": [
          "lineItems"
        ],
        "properties": {
          "trackingNumber": {
            "type": "string"
          },
          "carrier": {
            "type": "string"
          },
          "lineItems": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": [
                "orderLineItemId",
                "quantity"
              ],
              "properties": {
                "orderLineItemId": {
                  "type": "string"
                },
                "quantity": {
                  "type": "integer",
                  "minimum": 1
                }
              }
            }
          }
        }
      },
      "ItemStatus": {
        "type": "string",
        "enum": [
          "Active",
          "Draft",
          "Inactive",
          "Discontinued"
        ]
      },
      "ItemEnvelope": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/Item"
              }
            }
          }
        ]
      },
      "Item": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The item's id. Use it with `/by-id/` routes and as `brandItemId` in inventory."
          },
          "itemId": {
            "type": "string",
            "description": "The item code."
          },
          "brandId": {
            "type": "string"
          },
          "brandName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Filled in only on the 3PL lists."
          },
          "payload": {
            "$ref": "#/components/schemas/ItemPayload"
          },
          "channelSkus": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "SKUs sales channels carry for this item. Usually just `itemId`."
          },
          "channelLinks": {
            "type": "integer",
            "description": "How many channel variants link here. Greater than 0 with no `channelSkus` means the\nchannel sells it without a SKU, so its orders can't be matched.\n"
          },
          "createts": {
            "type": "string",
            "format": "date-time"
          },
          "modifyts": {
            "type": "string",
            "format": "date-time"
          },
          "createuserid": {
            "type": [
              "string",
              "null"
            ]
          },
          "modifyuserid": {
            "type": [
              "string",
              "null"
            ]
          },
          "createprogid": {
            "type": [
              "string",
              "null"
            ]
          },
          "modifyprogid": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "CreateItemRequest": {
        "type": "object",
        "required": [
          "itemId"
        ],
        "properties": {
          "itemId": {
            "type": "string",
            "maxLength": 40,
            "description": "The item code. Set it to the SKU your sales channels use, so their variants link."
          },
          "payload": {
            "$ref": "#/components/schemas/ItemPayload"
          }
        }
      },
      "BatchUpsertResult": {
        "type": "object",
        "properties": {
          "created": {
            "type": "integer"
          },
          "updated": {
            "type": "integer"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "rowNumber": {
                  "type": "integer"
                },
                "itemId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "ItemPayload": {
        "type": "object",
        "description": "Every field is optional. `Y`/`N` flags are single characters. Values longer than the\nlimits shown are refused.\n",
        "properties": {
          "title": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500
          },
          "extendedDescription": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          },
          "extendedDisplayDescription": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500
          },
          "productLine": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "keywords": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1000
          },
          "imageLocation": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255,
            "description": "Image URL."
          },
          "imageId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "imageLabel": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 200
          },
          "status": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/ItemStatus"
              },
              {
                "type": "null"
              }
            ],
            "description": "Defaults to `Active` on create."
          },
          "effectiveStartDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "effectiveEndDate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "unitCost": {
            "type": [
              "number",
              "null"
            ]
          },
          "costCurrency": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 20
          },
          "computedUnitCost": {
            "type": [
              "number",
              "null"
            ]
          },
          "pricingUomStrategy": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 20
          },
          "pricingUom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "bundlePriceStrat": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 6
          },
          "uom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40,
            "description": "Defaults to `EACH` on create."
          },
          "unitWeight": {
            "type": [
              "number",
              "null"
            ]
          },
          "unitWeightUom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "unitHeight": {
            "type": [
              "number",
              "null"
            ]
          },
          "unitHeightUom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "unitLength": {
            "type": [
              "number",
              "null"
            ]
          },
          "unitLengthUom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "unitWidth": {
            "type": [
              "number",
              "null"
            ]
          },
          "unitWidthUom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "minOrderQuantity": {
            "type": [
              "number",
              "null"
            ]
          },
          "maxOrderQuantity": {
            "type": [
              "number",
              "null"
            ]
          },
          "leadTime": {
            "type": [
              "integer",
              "null"
            ]
          },
          "processingTime": {
            "type": [
              "integer",
              "null"
            ]
          },
          "advanceNotificationTime": {
            "type": [
              "integer",
              "null"
            ]
          },
          "maxNotificationTime": {
            "type": [
              "number",
              "null"
            ]
          },
          "minNotificationTime": {
            "type": [
              "integer",
              "null"
            ]
          },
          "manufacturerName": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 50
          },
          "manufacturerItem": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "manufacturerItemDesc": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "countryOfOrigin": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "harmonizedCode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "nmfcCode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "nmfcClass": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "globalItemId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 128
          },
          "taxableFlag": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "taxProductCode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "defaultProductClass": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 10
          },
          "itemType": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "itemGroupCode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 20
          },
          "masterCatalogId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "department": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "itemClass": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "subClass": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "sizeCode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "colorCode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "model": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "modelItemUom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "upcComPreLen": {
            "type": [
              "integer",
              "null"
            ]
          },
          "ageVerificationCode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "subCatOrgCode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 24
          },
          "postingClassification": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "tagControlFlag": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "timeSensitive": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "defaultExpirationDays": {
            "type": [
              "integer",
              "null"
            ]
          },
          "isFifoTracked": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isSerialTracked": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "serializedFlag": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "numSecondarySerials": {
            "type": [
              "integer",
              "null"
            ]
          },
          "returnShippingLabelLevel": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isShippingAllowed": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isDeliveryAllowed": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isPickupAllowed": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isParcelShippingAllowed": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isAirShippingAllowed": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isForwardingAllowed": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isProcurementAllowed": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isReturnService": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "assumeInfiniteInventory": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "onhandSafetyFactorQty": {
            "type": [
              "number",
              "null"
            ]
          },
          "onhandSafetyFactorPct": {
            "type": [
              "number",
              "null"
            ]
          },
          "futureSafetyFactorPct": {
            "type": [
              "number",
              "null"
            ]
          },
          "useUnplannedInv": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isSubOnOrderAllowed": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isHazmat": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isFreezerRequired": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "storageType": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "pickingType": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "isShippingCntr": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "containerType": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 24
          },
          "containerSize": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 24
          },
          "capacityVolume": {
            "type": [
              "number",
              "null"
            ]
          },
          "capacityVolumeUom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "volumeAllowance": {
            "type": [
              "number",
              "null"
            ]
          },
          "maxCntrWeight": {
            "type": [
              "number",
              "null"
            ]
          },
          "maxCntrWeightUom": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 40
          },
          "emptyCntrWeight": {
            "type": [
              "number",
              "null"
            ]
          },
          "isModelItem": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "bundleFulfillmentMode": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2
          },
          "isConfigurable": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isPreConfigured": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isSoldSeparately": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "allowGiftWrap": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "isEligibleForShipDisc": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1
          },
          "primarySupplier": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 24
          }
        }
      },
      "InventoryLevel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "brandId": {
            "type": "string"
          },
          "brandItemId": {
            "type": "string"
          },
          "shipNodeId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Null for stock not assigned to a ship node."
          },
          "uom": {
            "type": "string"
          },
          "onHandQty": {
            "type": "integer"
          },
          "committedQty": {
            "type": "integer",
            "description": "Reserved for open orders."
          },
          "incomingQty": {
            "type": "integer",
            "description": "Expected on inbound shipments."
          },
          "availableQty": {
            "type": "integer",
            "description": "`onHandQty - committedQty`."
          },
          "safetyStockQty": {
            "type": "integer"
          },
          "reorderPoint": {
            "type": "integer"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "InventoryRow": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InventoryLevel"
          },
          {
            "type": "object",
            "properties": {
              "brandName": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Filled in only on the 3PL list."
              },
              "itemId": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The item code."
              },
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "channelSkus": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "shipNodeName": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        ]
      },
      "AdjustInventoryRequest": {
        "type": "object",
        "required": [
          "field",
          "delta",
          "adjustmentType"
        ],
        "properties": {
          "field": {
            "type": "string",
            "enum": [
              "on_hand_qty",
              "committed_qty",
              "incoming_qty"
            ]
          },
          "delta": {
            "type": "integer",
            "description": "The change, positive or negative. Not a new total.",
            "examples": [
              -20
            ]
          },
          "shipNodeId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The ship node. It must be able to fulfill for this brand. Omit to adjust stock not\nassigned to a ship node.\n"
          },
          "adjustmentType": {
            "$ref": "#/components/schemas/AdjustmentType"
          },
          "referenceType": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "ORDER",
              "SHIPMENT",
              "PURCHASE_ORDER",
              "MANUAL",
              "WMS_SYNC",
              "DEMO_SETUP",
              null
            ]
          },
          "referenceId": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 36
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AdjustmentType": {
        "type": "string",
        "description": "Why stock changed. For manual corrections use `MANUAL_ADJUSTMENT` or `CYCLE_COUNT`.",
        "enum": [
          "INITIAL_RECEIPT",
          "PO_INCOMING",
          "PO_RECEIVED",
          "CYCLE_COUNT",
          "MANUAL_ADJUSTMENT",
          "DAMAGED",
          "ORDER_COMMITTED",
          "ORDER_RELEASED",
          "ORDER_SHIPPED",
          "ORDER_RETURNED",
          "ORDER_ROUTED_COMMIT",
          "ORDER_ROUTED_RELEASE",
          "LOGIWA_SYNC"
        ]
      },
      "InventoryAdjustment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "inventoryLevelId": {
            "type": "string"
          },
          "brandId": {
            "type": "string"
          },
          "brandItemId": {
            "type": "string"
          },
          "fieldAdjusted": {
            "type": "string",
            "enum": [
              "on_hand_qty",
              "committed_qty",
              "incoming_qty"
            ]
          },
          "quantityDelta": {
            "type": "integer"
          },
          "adjustmentType": {
            "$ref": "#/components/schemas/AdjustmentType"
          },
          "referenceType": {
            "type": [
              "string",
              "null"
            ]
          },
          "referenceId": {
            "type": [
              "string",
              "null"
            ]
          },
          "notes": {
            "type": [
              "string",
              "null"
            ]
          },
          "createdBy": {
            "type": "string",
            "description": "The user who made it, or `system`."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ShipNodeEnvelope": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Envelope"
          },
          {
            "type": "object",
            "properties": {
              "data": {
                "$ref": "#/components/schemas/ShipNode"
              }
            }
          }
        ]
      },
      "ShipNode": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "owner_key": {
            "type": "string",
            "description": "The owning brand's or 3PL's id."
          },
          "owner_type": {
            "$ref": "#/components/schemas/OwnerType"
          },
          "description": {
            "type": "string",
            "description": "The node's name."
          },
          "node_type": {
            "$ref": "#/components/schemas/ShipNodeType"
          },
          "activate_flag": {
            "type": "string",
            "enum": [
              "Y",
              "N"
            ]
          },
          "ship_node_address_line1": {
            "type": [
              "string",
              "null"
            ]
          },
          "ship_node_address_line2": {
            "type": [
              "string",
              "null"
            ]
          },
          "ship_node_city": {
            "type": [
              "string",
              "null"
            ]
          },
          "ship_node_state": {
            "type": [
              "string",
              "null"
            ]
          },
          "ship_node_zip": {
            "type": [
              "string",
              "null"
            ]
          },
          "ship_node_country": {
            "type": "string"
          },
          "latitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "longitude": {
            "type": [
              "number",
              "null"
            ]
          },
          "address_verified": {
            "type": "boolean"
          },
          "total_sqft": {
            "type": [
              "integer",
              "null"
            ]
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rejection_ttl_minutes": {
            "type": "integer",
            "description": "How long an order this node rejected stays away from it."
          },
          "contact_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "contact_email": {
            "type": [
              "string",
              "null"
            ]
          },
          "contact_phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "manager_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "manager_email": {
            "type": [
              "string",
              "null"
            ]
          },
          "manager_phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "kpi_otd_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "kpi_error_rate_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "kpi_avg_processing_hours": {
            "type": [
              "number",
              "null"
            ]
          },
          "kpi_returns_rate_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "kpi_inventory_accuracy_pct": {
            "type": [
              "number",
              "null"
            ]
          },
          "kpi_orders_last_12mo": {
            "type": [
              "integer",
              "null"
            ]
          },
          "kpi_updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "charges": {
            "type": "object",
            "description": "A 3PL node's fee schedule. Present only on `GET /api/v1/ship-nodes/{id}`.",
            "additionalProperties": true
          }
        }
      },
      "ShipNodeType": {
        "type": "string",
        "enum": [
          "WAREHOUSE",
          "STORE",
          "TEMPORARY_POPUP_STORE"
        ]
      },
      "ShipNodeRequest": {
        "type": "object",
        "description": "On create, `description` is required. On update, send only what changes.",
        "properties": {
          "description": {
            "type": "string",
            "maxLength": 100
          },
          "node_type": {
            "$ref": "#/components/schemas/ShipNodeType"
          },
          "activate_flag": {
            "type": "string",
            "enum": [
              "Y",
              "N"
            ]
          },
          "ship_node_address_line1": {
            "type": "string",
            "maxLength": 500
          },
          "ship_node_address_line2": {
            "type": "string",
            "maxLength": 500
          },
          "ship_node_city": {
            "type": "string",
            "maxLength": 100
          },
          "ship_node_state": {
            "type": "string",
            "maxLength": 100
          },
          "ship_node_zip": {
            "type": "string",
            "maxLength": 20
          },
          "ship_node_country": {
            "type": "string",
            "maxLength": 10,
            "default": "US"
          },
          "latitude": {
            "type": "number"
          },
          "longitude": {
            "type": "number"
          },
          "address_verified": {
            "type": "boolean"
          },
          "total_sqft": {
            "type": "integer"
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rejection_ttl_minutes": {
            "type": "integer"
          },
          "contact_name": {
            "type": "string"
          },
          "contact_email": {
            "type": "string"
          },
          "contact_phone": {
            "type": "string"
          },
          "manager_name": {
            "type": "string"
          },
          "manager_email": {
            "type": "string"
          },
          "manager_phone": {
            "type": "string"
          },
          "kpi_otd_pct": {
            "type": "number"
          },
          "kpi_error_rate_pct": {
            "type": "number"
          },
          "kpi_avg_processing_hours": {
            "type": "number"
          },
          "kpi_returns_rate_pct": {
            "type": "number"
          },
          "kpi_inventory_accuracy_pct": {
            "type": "number"
          },
          "kpi_orders_last_12mo": {
            "type": "integer"
          }
        }
      },
      "ChannelType": {
        "type": "string",
        "enum": [
          "SHOPIFY",
          "WOOCOMMERCE",
          "AMAZON",
          "TIKTOK_SHOP",
          "BIGCOMMERCE",
          "MANUAL",
          "API",
          "WEBSITE",
          "EDI",
          "CALL_CENTER"
        ]
      },
      "Channel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/ChannelType"
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "isActive": {
            "type": "boolean"
          },
          "shopifyDomain": {
            "type": [
              "string",
              "null"
            ]
          },
          "webhookUrl": {
            "type": [
              "string",
              "null"
            ]
          },
          "inventoryPushIntervalSeconds": {
            "type": "integer",
            "description": "How often stock is pushed to the channel."
          },
          "connected": {
            "type": "boolean",
            "description": "For Shopify, whether the store's credentials are in place. Always true for other types."
          },
          "reauthRequired": {
            "type": "boolean"
          }
        }
      },
      "CreateChannelRequest": {
        "type": "object",
        "properties": {
          "type": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ChannelType"
              }
            ],
            "default": "SHOPIFY"
          },
          "name": {
            "type": "string",
            "description": "Required for every type except `SHOPIFY`."
          },
          "shopifyDomain": {
            "type": "string",
            "description": "For `SHOPIFY`, e.g. `your-store.myshopify.com`."
          },
          "webhookUrl": {
            "type": "string"
          },
          "apiKey": {
            "type": "string",
            "description": "A credential for the channel; stored encrypted, never returned."
          }
        }
      },
      "PartnerChannel": {
        "type": "object",
        "properties": {
          "channelId": {
            "type": "string"
          },
          "channelName": {
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/ChannelType"
          },
          "brandId": {
            "type": "string"
          },
          "brandName": {
            "type": "string"
          },
          "shopifyDomain": {
            "type": [
              "string",
              "null"
            ]
          },
          "isActive": {
            "type": "boolean"
          },
          "inventoryPushIntervalSeconds": {
            "type": "integer"
          },
          "connected": {
            "type": "boolean"
          },
          "reauthRequired": {
            "type": "boolean"
          }
        }
      },
      "ProductSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "externalId": {
            "type": "string",
            "description": "The product's id in the channel."
          },
          "title": {
            "type": "string"
          },
          "brandName": {
            "type": [
              "string",
              "null"
            ]
          },
          "productType": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string"
          },
          "skuCount": {
            "type": "integer"
          }
        }
      },
      "ProductDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "externalId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "brandName": {
            "type": [
              "string",
              "null"
            ]
          },
          "productType": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string"
          },
          "skus": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "skuCode": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Null when the channel has no SKU for the variant."
                },
                "upc": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "unitPriceCents": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "format": "int64"
                },
                "status": {
                  "type": "string"
                },
                "attributes": {
                  "type": "object",
                  "description": "Option name to value, e.g. `{\"Size\": \"M\"}`.",
                  "additionalProperties": {
                    "type": "string"
                  }
                },
                "qtyAvailable": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "ProductSyncJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "RUNNING",
              "COMPLETED",
              "FAILED"
            ]
          },
          "productsProcessed": {
            "type": "integer"
          },
          "productsSkipped": {
            "type": "integer"
          },
          "skusUpserted": {
            "type": "integer"
          },
          "issuesFlagged": {
            "type": "integer",
            "description": "Variants needing attention, such as a missing SKU or inventory tracking turned off."
          },
          "errorMessage": {
            "type": [
              "string",
              "null"
            ]
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "InventoryPushJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "channelId": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "RUNNING",
              "COMPLETED",
              "FAILED"
            ]
          },
          "skusPushed": {
            "type": "integer"
          },
          "skusSkipped": {
            "type": "integer"
          },
          "errorMessage": {
            "type": [
              "string",
              "null"
            ]
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      }
    }
  }
}