Incremental Update

Update individual inventory listings as they change. Ideal for real-time sync from your POS or inventory management system.

PATCH/inventoryinventory:write
Incremental Inventory Update

Update specific inventory items. Use this for real-time sync when individual listings change.

On larger screens, use the API Playground panel on the right to try this endpoint.
NameTypeRequiredDescription
itemsarrayRequiredArray of inventory items to update
strictbooleanOptionalIf true, fail entire batch on any error. Default: false (partial success)
bash
curl -X PATCH "https://api.ctcgx.com/api/v1/inventory" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "tcgplayerId": "12345",
      "quantity": 3,
      "price": 649,
      "condition": "NM",
      "finish": "nonfoil",
      "action": "upsert"
    },
    {
      "tcgplayerId": "12345",
      "quantity": 1,
      "price": 1299,
      "condition": "NM",
      "finish": "foil",
      "action": "upsert"
    },
    {
      "scryfallId": "abc-123-def",
      "condition": "LP",
      "finish": "nonfoil",
      "action": "delete"
    }
  ]
}'

Response

Returns counts of items processed, created, updated, deleted, and any errors.

json
{
  "success": true,
  "processed": 3,
  "created": 0,
  "updated": 2,
  "deleted": 1,
  "failed": 0,
  "errors": []
}

Item Structure

Each item supports the same fields as the Full Inventory Sync endpoint, plus an action field:

FieldTypeDescription
actionstring"upsert" (default) or "delete"
+ all fields from Full Sync item structure (external IDs, condition, finish, grading, etc.)

Targeting Specific Variants

The same product ID can have multiple listings. To update a specific one, include the variant fields that identify it:

// Update only the NM foil listing (leaves nonfoil unchanged)
{
  "items": [{
    "tcgplayerId": "12345",
    "condition": "NM",
    "finish": "foil",
    "quantity": 2,
    "price": 1499
  }]
}

// Update the Japanese 1st Edition listing
{
  "items": [{
    "tcgplayerId": "12345",
    "condition": "NM",
    "finish": "nonfoil",
    "language": "Japanese",
    "edition": "1st Edition",
    "quantity": 1,
    "price": 2999
  }]
}

Use Cases

Incremental updates are perfect for:

  • Real-time POS integration - Update quantities immediately when items sell
  • Price changes - Update prices without re-syncing entire inventory
  • New arrivals - Add new listings as they're received
  • Stock removal - Delete listings when items are no longer available

Setting Quantity to Zero

Setting quantity: 0 with action: "upsert" will keep the listing but mark it as out of stock. To completely remove the listing, use action: "delete".

// Mark as out of stock (keeps listing)
{
  "tcgplayerId": "12345",
  "quantity": 0,
  "price": 599,
  "action": "upsert"
}

// Completely remove listing
{
  "tcgplayerId": "12345",
  "action": "delete"
}

Error Handling

By default, the API uses partial success mode: valid items are processed while failed items are collected in the errors array. This allows you to handle failures individually without blocking the entire batch.

{
  "success": false,
  "processed": 1,
  "created": 0,
  "updated": 1,
  "deleted": 0,
  "failed": 2,
  "errors": [
    {
      "index": 0,
      "externalId": "invalid-id-123",
      "error": "Product not found: tcgplayerId=\"invalid-id-123\" does not match any product in our database."
    },
    {
      "index": 2,
      "externalId": "another-bad-id",
      "error": "Missing required field \"price\" for scryfallId=\"another-bad-id\". Price is required for upsert operations."
    }
  ]
}
// Strict mode - fail entire batch on any error
{
  "strict": true,
  "items": [
    { "tcgplayerId": "12345", "quantity": 3, "price": 649 },
    { "tcgplayerId": "invalid", "quantity": 1, "price": 199 }
  ]
}

// Response: Nothing processed because one item failed
{
  "success": false,
  "processed": 0,
  "failed": 1,
  "errors": [{ "index": 1, "error": "Product not found..." }]
}

API Playground

Select an endpoint from the documentation to try it out here.