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

Productgoes inside Cartonstored in Warehousetracked 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.