Skip to main content
POST

Intro

Sets the complete variant tree (variations → optional sub-variations → sub-variants) for a product in one call — a full replace, not an incremental add.

Context

Pairs with Get Product Variants, which returns the tree this endpoint writes, and with Marketplace Products, whose product record this endpoint updates (has_variation, total_quantity). It operates on any product you own or that belongs to an active sub-merchant in your marketplace — the same ownership rule used across the product endpoints.

Hows

Orphan cleanup is real and destructive. If you fetch the current tree via Get Variants, remove one variant client-side, and POST the rest, the removed variant (and any of its sub-variants) is permanently deleted server-side — there’s no soft-delete or undo. Always send the entire desired tree, not a partial update.

Path Parameters

integer
required
A product you own, or a product owned by an active sub-merchant in your marketplace (marketplace operators can manage sub-merchant product variants directly).

Request Body

string
required
Label for the top-level variation axis, e.g. "size".
string
Display label shown to customers. Defaults to variation_type if omitted.
boolean
Whether each variation has a nested sub-variation axis (e.g. size → color). Recalculated server-side after processing — the server checks whether any variations[].sub_variation.sub_variants actually has entries and overwrites whatever you sent with that computed value. Sending true with no real sub-variants will be silently corrected to false.
integer
default:"0"
Only used if you provide it and it’s truthy — otherwise it’s computed server-side as the sum of each variation’s variation_quantity. Either way, a second pass then recomputes the true total from the full tree (including sub-variant quantities) and writes that final number back to both the variation tree and the product record — so don’t rely on the value you sent surviving unchanged.
array
required
Non-empty array. Each item:

Response

The response data here is a flat ProductVariation record — it does not include the nested variations/sub_variation/sub_variants tree. If you need the full tree back (e.g. to get server-confirmed nesting), call Get Variants right after. This asymmetry between POST and GET response shapes is intentional in the current implementation, not a bug — don’t rely on the POST response for anything beyond id/total_quantity.

Side Effects

  • Recomputes and overwrites total_quantity on both the variation tree and the parent product record.
  • Sets the product’s has_variation flag to true unconditionally, even if variations ends up empty after processing.
  • Deletes any variant/sub-variation/sub-variant rows not present in this request’s variations array (see warning above).

Error Codes

Whys

Full-replace-on-write (rather than incremental add/update/delete operations) keeps the client’s view of the variant tree and the server’s in lockstep with a single call — the client always sends its complete intended state, and the server makes reality match it, rather than requiring three separate endpoints (add variant, update variant, delete variant) that a client could call out of order or partially. Client-generated UUIDs make this safe for the common editing pattern of “fetch the tree, mutate it locally, send the whole thing back” — reusing an id updates that exact node instead of creating a duplicate. Recomputing total_quantity and has_sub_variants server-side rather than trusting client-sent values keeps the product’s stock and variant-shape fields consistent with what was actually stored, even if the client’s math was wrong or stale.

Why nots

This is not an incremental/patch operation — sending a subset of the tree deletes everything you left out. It does not return the full tree in its response — call Get Variants if you need to confirm what was actually stored. It does not give you field-level validation errors for a missing id — the response is a generic failure message, so validate that every node has an id before sending rather than relying on the API to tell you which one is missing.