API Docs

Products

scope: inventory

Create and manage your product catalog. Products represent the items your organization stores and ships. Each product has a unique SKU that cannot be changed after creation.

Where products fit in

Product→goes inside Carton→stored in Warehouse→tracked via Stock Levels

Products are the foundation of your inventory. Create products first, then define cartons that contain them.

Endpoints

GET
/v0/inventory/products

List all products with search, filter, and sort

GET
/v0/inventory/products/:id

Get a single product by ID

GET
/v0/inventory/products/:id/history

Get change history for a product

POST
/v0/inventory/products

Create a new product

PUT
/v0/inventory/products/:id

Update a product (name, description)

DELETE
/v0/inventory/products/:id

Delete a product (soft-delete, must have 0 stock)

PATCH
/v0/inventory/products/:id/restore

Restore a previously deleted product

List Products

Returns a paginated list of products. By default, deleted products are excluded.

Query Parameters

ParameterTypeDescription
searchstringPartial match on product name or SKU
skustringFilter by exact SKU
includeDeletedbooleanInclude soft-deleted products (default: false)
sortBystringSort field: name, sku, createdAt, updatedAt (default: createdAt)
sortOrderstringSort direction: asc or desc (default: desc)
skipnumberNumber of records to skip (default: 0)
takenumberNumber of records to return (default: 10, max: 50)
curl
curl "https://api.3plguys.com/v0/inventory/products?search=egg&sortBy=name&sortOrder=asc" \
-H "Authorization: Bearer <token>"
Node.js
const res = await fetch(
"https://api.3plguys.com/v0/inventory/products?search=egg&sortBy=name&sortOrder=asc",
{ headers: { Authorization: `Bearer ${token}` } }
);
const products = await res.json();
Python
res = httpx.get(
"https://api.3plguys.com/v0/inventory/products",
params={"search": "egg", "sortBy": "name", "sortOrder": "asc"},
headers={"Authorization": f"Bearer {token}"},
)
products = res.json()
Response
[
{
"id": "1",
"name": "Egg Shells",
"sku": "ABC123",
"description": "Premium egg shells for baking",
"createdAt": "2025-01-15T08:30:00.000Z",
"updatedAt": "2025-02-20T14:00:00.000Z",
"deletedAt": null
}
]

Get Product

Retrieve a single product by its ID. Returns 404 if the product does not exist or belongs to another organization.

GET /v0/inventory/products/1
{
"id": "1",
"name": "Egg Shells",
"sku": "ABC123",
"description": "Premium egg shells for baking",
"createdAt": "2025-01-15T08:30:00.000Z",
"updatedAt": "2025-02-20T14:00:00.000Z",
"deletedAt": null
}

Create Product

Request Body

ParameterTypeDescription
name*stringProduct name (minimum 2 characters)
sku*stringUnique SKU within your organization (minimum 2 characters, immutable)
descriptionstringOptional product description
curl
curl -X POST "https://api.3plguys.com/v0/inventory/products" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "name": "Egg Shells", "sku": "ABC123", "description": "Premium egg shells for baking" }'
Node.js
const res = await fetch("https://api.3plguys.com/v0/inventory/products", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Egg Shells",
sku: "ABC123",
description: "Premium egg shells for baking",
}),
});
const product = await res.json();
Python
res = httpx.post(
"https://api.3plguys.com/v0/inventory/products",
json={"name": "Egg Shells", "sku": "ABC123", "description": "Premium egg shells for baking"},
headers={"Authorization": f"Bearer {token}"},
)
product = res.json()
Request Body
{
"name": "Egg Shells",
"sku": "ABC123",
"description": "Premium egg shells for baking"
}
Response
{
"id": "1",
"name": "Egg Shells",
"sku": "ABC123",
"description": "Premium egg shells for baking",
"createdAt": "2025-01-15T08:30:00.000Z",
"updatedAt": "2025-01-15T08:30:00.000Z",
"deletedAt": null
}

SKU is immutable

The SKU cannot be changed after the product is created. If you need a different SKU, create a new product and delete the old one.

Update Product

Request Body

ParameterTypeDescription
name*stringProduct name (minimum 2 characters)
descriptionstringOptional product description
PUT /v0/inventory/products/1
{
"name": "Egg Shells (Large)",
"description": "Updated description"
}
Response
{
"id": "1",
"name": "Egg Shells (Large)",
"sku": "ABC123",
"description": "Updated description",
"createdAt": "2025-01-15T08:30:00.000Z",
"updatedAt": "2025-03-04T10:15:00.000Z",
"deletedAt": null
}

Delete Product

Soft-deletes a product. The product must have zero stock across all warehouses. Deleted products are excluded from list results unless includeDeleted=true is passed.

DELETE /v0/inventory/products/1
{
"id": "1",
"name": "Egg Shells",
"sku": "ABC123",
"description": "Premium egg shells for baking",
"createdAt": "2025-01-15T08:30:00.000Z",
"updatedAt": "2025-03-04T12:00:00.000Z",
"deletedAt": "2025-03-04T12:00:00.000Z"
}

Restore Product

Restores a previously deleted product, making it active again.

PATCH /v0/inventory/products/1/restore
{
"id": "1",
"name": "Egg Shells",
"sku": "ABC123",
"description": "Premium egg shells for baking",
"createdAt": "2025-01-15T08:30:00.000Z",
"updatedAt": "2025-03-04T12:05:00.000Z",
"deletedAt": null
}

Product History

Returns a paginated list of change events for a product, including creation, updates, deletes, restores, and stock changes. Only publicly visible entries are returned.

Query Parameters

ParameterTypeDescription
skipnumberNumber of records to skip (default: 0)
takenumberNumber of records to return (default: 10, max: 50)
curl
curl "https://api.3plguys.com/v0/inventory/products/1/history?take=10" \
-H "Authorization: Bearer <token>"
Node.js
const res = await fetch(
`https://api.3plguys.com/v0/inventory/products/${productId}/history?take=10`,
{ headers: { Authorization: `Bearer ${token}` } }
);
const history = await res.json();
Python
res = httpx.get(
f"https://api.3plguys.com/v0/inventory/products/{product_id}/history",
params={"take": 10},
headers={"Authorization": f"Bearer {token}"},
)
history = res.json()
Response
[
{
"id": "15",
"type": "customer",
"description": "Updated product Egg Shells (ABC123)",
"createdAt": "2026-03-04T10:15:00.000Z"
},
{
"id": "12",
"type": "admin",
"description": "Updated carton count '10' changed to '15' for '10-Pack Case' carton type.",
"createdAt": "2026-03-02T08:00:00.000Z"
},
{
"id": "1",
"type": "customer",
"description": "Created new product Egg Shells (ABC123)",
"createdAt": "2025-01-15T08:30:00.000Z"
}
]

Response Fields

ParameterTypeDescription
id*stringHistory entry ID
type*stringWho made the change: system, customer, or admin
description*stringHuman-readable description of what changed
createdAt*ISO 8601When the change occurred

Error Responses

400SKU is already in use in your inventory

Returned when creating a product with a SKU that already exists in your organization.

400Cannot delete a product that still has stock

Returned when attempting to delete a product that has cartons in any warehouse.

404Product not found

The product ID does not exist or does not belong to your organization.