Products & Variants
Products & Variants
The eBay product model
In eBay, a product (called an inventory item) is identified by a SKU that you assign. The SKU is the product's permanent ID — all subsequent operations (offers, updates, variant groups) reference it by SKU, not by a platform-generated ID.
A product contains the item's details — title, description, images, condition, dimensions, weight — but is not publicly listed until you create an Offer for it. Think of it as a catalog record that is separate from the public listing. See Listings & Offers for the offer flow.
API endpoints
| Method | Path | Description | API Reference |
|---|---|---|---|
| POST | /api/v1/products | Create a product (v1) | ref |
| POST | /api/v2/products | Create a product (v2) | ref |
| POST | /api/v1/products/batch | Create multiple products in batch | ref |
| GET | /api/v2/products | List all inventory items | ref |
| GET | /api/v2/products/{sku} | Get a single product | ref |
| PUT | /api/v2/products/{sku} | Update product or inventory/price | ref |
| PUT | /api/v2/products/{sku} | Update inventory & price only | ref |
| DELETE | /api/v2/products/{sku} | Delete a product | ref |
| GET | /api/v1/products/{key}/variants | Get product group | ref |
| POST | /api/v1/products/{key}/variants | Create product group | ref |
| PUT | /api/v1/products/{key}/variants | Update product group | ref |
v1 vs v2 for product creation
For eBay, POST /api/v1/products is recommended over POST /api/v2/products. This is specific to eBay and does not apply to other platforms.
| Version | How it works | When to use |
|---|---|---|
v1 /api/v1/products | Passes your request body directly to eBay's API without transformation | Recommended. Lets you use eBay's exact native format, which you control fully |
v2 /api/v2/products | Goes through EcartAPI's normalized product schema before reaching eBay | Use for cross-platform workflows; less flexible for eBay-specific fields |
eBay's product requirements — especially item specifics (aspects), package dimensions, and category-specific fields — change frequently. Using v1 means you work directly with eBay's native format and are not constrained by EcartAPI's normalization layer. This is particularly important for offers and variant groups, where eBay's API structure is more complex.
Creating a product
Both v1 and v2 call eBay's createOrReplaceInventoryItem endpoint. sku and marketplaceId are required. If a product with the same SKU already exists, the request returns an error — there is no upsert; you must delete and recreate.
Using v1 (recommended) — native eBay format:
POST /api/v1/products
{
"product": {
"sku": "MY-PRODUCT-001",
"marketplaceId": "EBAY_US",
"condition": "NEW",
"product": {
"title": "My Product Title",
"description": "Product description",
"aspects": {
"Brand": ["My Brand"],
"Type": ["T-Shirt"]
},
"imageUrls": ["https://example.com/image.jpg"],
"packageWeightAndSize": {
"dimensions": {
"height": 10,
"length": 15,
"width": 10,
"unit": "INCH"
},
"weight": {
"value": 0.5,
"unit": "POUND"
}
}
},
"availability": {
"shipToLocationAvailability": {
"quantity": 10
}
}
}
}Valid condition values: NEW, LIKE_NEW, NEW_OTHER, NEW_WITH_DEFECTS, CERTIFIED_REFURBISHED, SELLER_REFURBISHED, USED_EXCELLENT, USED_ACCEPTABLE
Price vs. stock: which endpoint updates what
This is one of the most common points of confusion:
| What you want to change | Endpoint | Payload |
|---|---|---|
| Quantity only | PUT /api/v2/products/{sku} | { "product": { "quantity": "10" } } — send only quantity, nothing else |
| Price only | PUT /api/v1/listings/{offerId} | { "listing": { "pricingSummary": { "price": { "currency": "USD", "value": "24.99" } } } } |
| Quantity + price together | PUT /api/v2/products/{sku} | Include an offers array: { "product": { "offers": [{ "id": "OFFER_ID", "quantity": "10", "price": { "currency": "USD", "value": "24.99" } }] } } |
| Product details (title, images, condition, aspects) | PUT /api/v2/products/{sku} | Full product fields — do not include quantity or offers |
Price lives on the Offer, not the inventory item. Sending a
pricefield inPUT /api/v2/products/{sku}without anoffersarray returns200 OKbut does not change the price on eBay. Always update price viaPUT /api/v1/listings/{offerId}or via theoffersarray when updating both together.
Deleting a product also deletes all unpublished offers for that SKU and removes it from any inventory item groups.
Migrating existing listings
If your eBay listings were created outside of the Inventory API — directly on eBay's site or via the old Trading API — they must be migrated before you can manage them via EcartAPI. Once migrated, they become Inventory API items accessible by SKU through all product endpoints.
Eligibility requirements
Before running the migration, verify that each listing meets all of the following conditions. Listings that don't comply will be rejected by eBay:
| Requirement | Details |
|---|---|
| Listing type | Must be Fixed-Price |
| Listing duration | Must be GTC (Good 'til Cancelled) |
| SKU assigned | Every item must have a seller-defined SKU. For multi-variation listings, each variation must also have its own individual SKU |
| Business Policies | Fulfillment, payment, and return policies must be applied. Legacy shipping/payment/return fields are not accepted. The payment policy must have immediate payment enabled and PayPal as the only payment method |
| Location | Listing must include a postal/zip code or city. Country is always present in the Trading API and does not need to be added manually |
Migration steps
GET /api/v1/products/listings— fetch listings to get their IDs and verify SKUs are assigned → ref- Verify each listing meets all eligibility requirements above
POST /api/v2/products/listings/migrate— convert listings to Inventory API format → refPUT /api/v2/products/{sku}— update inventory and price post-migration → ref
POST /api/v2/products/listings/migrate
{
"listings": {
"ids": [
"123456789"
]
}
}Critical — variant listings and stock: If the listing contains variants, every variant must have at least 1 unit in stock before running the migration. Any variant with zero stock will be silently excluded — the product will be imported without those variants and they will not appear in
GET /productsor the product group. Variants with zero stock will show"status": "not available"in the offers response but will be absent from the Inventory API entirely.
Migration is a one-time operation. Once a listing is migrated, eBay returns an error if you attempt to migrate it again:
"This listing is already migrated". There is no force or re-migrate option.
Recovery: when a variant was missed during migration
If a variant was excluded due to zero stock, you cannot re-run the migration. Add it manually:
1. Create the missing product → POST /api/v1/products (ref) using the same structure as the other variants (same title, images, aspects, weight), only changing the SKU.
2. Update the product group to include the new SKU. Always fetch the current group first — any omitted field will be overwritten:
GET /api/v1/products/{inventoryItemGroupKey}/variants
POST /api/v1/products/{inventoryItemGroupKey}/variants ← include new SKU in variantSKUs
3. Create and publish the offer for the missing SKU → POST /api/v1/products/listings (ref), matching the categoryId, listingPolicies, merchantLocationKey, and pricingSummary of the existing offers.
Last resort: If eBay rejects linking the new SKU to the already-migrated group, delete the product from eBay and recreate the entire variant structure from scratch — ensuring all variants have at least 1 unit in stock before migrating.
Product Variants (Groups)
eBay manages variants through Inventory Item Groups — a group that links multiple individual products (SKUs) together as variants, differentiated by aspects (e.g., Color, Size).
Prerequisites before publishing a variant group
- Payoneer account linked
- Enrolled in
SELLING_POLICY_MANAGEMENT - Fulfillment, payment, and returns policies created
- At least one location with a valid postal code
See Getting Started for the setup flow.
Complete flow: create and publish a variant group
Step 1 — Create variant products in batch → ref
POST /api/v1/products/batch
One entry per variant SKU. All variants should share the same base product.aspects but have different SKUs and variant-specific aspect values.
Step 2 — Create the Product Group → ref
POST /api/v1/products/{inventoryItemGroupKey}/variants{
"variant": {
"inventoryItemGroupKey": "MY-GROUP-001",
"marketplaceId": "EBAY_US",
"title": "My Product with Variants",
"description": "Full product description",
"aspects": {
"Color": ["Red", "Blue"],
"Size": ["S", "M", "L"]
},
"imageUrls": ["https://example.com/main-image.jpg"],
"variantSKUs": ["SKU-RED-S", "SKU-RED-M", "SKU-BLUE-S", "SKU-BLUE-M"]
}
}Step 3 — Create offers in batch → ref
POST /api/v1/products/listings/batch
One offer per variant SKU. Each must include fulfillmentPolicyId, paymentPolicyId, returnPolicyId, and merchantLocationKey.
Step 4 — Publish the group → ref
POST /api/v1/products/{inventoryItemGroupKey}/variants/publish
Calls eBay's publish_by_inventory_item_group, making the entire group live simultaneously.
Updating a product group
Always retrieve the current group first → ref. Then resubmit the full updated object — any omitted field will be overwritten or lost.
Updated 2 days ago