Skip to main content
virtual.fit resolves storefront products from your synced catalog. Use the management API for continuous server-to-server sync. Use CSV for scheduled or manual imports.
The current contract is schema version 2. Omit schema_version for all new integrations. Send schema_version: 1 only from an existing image-only integration that needs legacy update behavior.
Send management API requests to https://api.virtual.fit.

Choose a sync method

Push changes as they happen. This is the best option when your backend knows the current variants, prices, or inventory.
Keep the API key on your server. Never include it in storefront JavaScript.

Find your site ID

In virtual.fit, open Custom JS → Sync Products and copy the Storefront Site ID from the Storefront Credentials section. The site ID is a UUID used in the site_id path parameter. It is different from the public site key, your workspace ID, and any ID from your commerce platform. For server-side discovery, call the current-site endpoint with your API key and store the returned site.id value for later requests:

Start with the smallest useful product

You can send the title and image first. Add variants, stock, prices, options, and size charts later under the same product ID.
For a new product, include:
  • A stable product ID in the request URL or product_id CSV column.
  • title.
  • At least one public product image.
Omitted fields stay unchanged on later updates. This lets a feed publish the essentials quickly and enrich the product progressively.

Choose a durable product ID

product_id is the permanent identity of the product inside one site. It is case-sensitive and can be a numeric ID, UUID, or URL-safe string.
  • Prefer an immutable catalog or database ID.
  • Keep one ID for the product when prices, images, options, or variants change.
  • Do not derive it from the title, URL, handle, or current variant combination.
  • Keep it within 255 UTF-8 bytes and URL-encode it in API paths.
A product can begin without variants and gain them later under the same product_id. This does not create a second product or require a migration.

Send products with variants

A product holds shared merchandising data. A variant holds one exact purchasable combination, such as Floral / Petite / 2.
Send only combinations that shoppers can actually select. Option values describe available choices; they do not create a Cartesian product of variants.

Send stock updates

Use the same product upsert endpoint when stock changes. For an existing product, send only the changed variants. You do not need to resend the title, images, prices, or unchanged variants.
Identify each variant by the same source_variant_id used during the initial sync.
For exact variants:
  • Send available: true when the variant can be purchased and false when it is sold out.
  • Send inventory_quantity when your source provides an exact count. Quantity alone does not set available.
  • Send inventory_observed_at as the RFC 3339 time when your source reported the stock. If you omit it, virtual.fit uses the request time.
  • Keep the timestamp from the source. An older observation does not replace newer stock for the same variant.
  • Omit variants_complete from a targeted stock update. Set it to true only when the request contains the complete authoritative variant list.
  • Refresh stock regularly. virtual.fit treats stale inventory as unknown instead of claiming that a variant is in stock.
enabled controls whether the product can use the fitting room. It is not a stock field. Keep enabled unchanged when only inventory changes. For an existing product, omitting it from an upsert preserves the current state; use the dedicated enable-state endpoint when changing availability by itself.

Field reference

Fields are ordered by how commonly a new integration needs them. Auto-detected when omitted means virtual.fit derives the value from the supplied variants, option names, swatches, or media.

Product fields

string
required
Stable product ID in the request URL. Keep it unchanged when variants, prices, inventory, or media change.
string
required
Shopper-facing product name. Required when creating a product.
object[]
required
Shared product media. A new product needs at least one public image. See the image object reference.
string
Required for most Custom JavaScript storefronts. Send the stable storefront slug when the site resolves product URLs by handle. You may omit it only when URL resolution uses product_id.
string
Public canonical product URL. Must use HTTP or HTTPS.
boolean
default:"true"
Whether the product is enabled in the fitting room. This is separate from upstream sale availability.
boolean
Current source-reported sale availability when it is known. Omit or send null when unknown. Usually derived from exact variants or synced from the source; variant availability is more precise when variants exist.
number
Current overall customer rating on a 0–5 scale. Omit when the source does not expose an aggregate rating.
number
Number of customer reviews included in the current overall rating. Must be zero or greater.
object
Product-level selling price. A variant price overrides it for that variant. Expand for the exact object shape.
object
Product-level original or pre-sale price. Uses the same amount and currency shape as price.
object[]
Exact purchasable combinations. An empty array is valid. Expand for variant identity, selections, inventory, pricing, and media fields, or open the variant object reference.
boolean
default:"false"
When true, the supplied variant list is authoritative. Omitted variants become inactive. Send true with variants: [] for a genuinely variantless product.
object[]
Choice axes, labels, swatches, and size metadata. Auto-detected when omitted: virtual.fit derives the minimum option structure from variants[].option_values. Send options when you have source labels, ordering, swatches, or explicit size metadata. See the option object reference.
object[]
Product-wide or option-scoped size chart references. Stored now for future size-aware recommendations; they do not change today’s visual recommendation ranking. See the size-chart reference.
object[]
Optional measured garment dimensions by size. Use canonical dimension names such as bust, chest, waist, hips, shoulder_width, sleeve_length, total_length, inseam, front_rise, back_rise, thigh, or leg_opening. Use cm or in.
object[]
Optional product-page model or mannequin fit facts. Send the worn size and any source-reported body measurements. These fields can improve future size recommendations and remain optional.
string
Brand or designer name.
string
Merchant-facing product type. Usually populated automatically when the source exposes it.
string
Optional plain-text product description. Useful enrichment, but not required for fitting-room product matching.
string
Optional product-specific try-on guidance.
string
Optional concise garment naming override used to describe the item during try-on. Auto-detected when omitted.
boolean
Whether the product still exists and is active in the source catalog. Send false for archived or removed products.
string
Optional unmodified status from the source system, such as ACTIVE, ARCHIVED, or DRAFT. It is preserved for diagnostics and is not a normalized enum.
string
RFC 3339 timestamp for the source record. Usually populated automatically.
number
default:"2"
Omit for the current contract. The only accepted explicit values are 1 for a legacy image-only request and 2 for the current contract.
object
Optional ordering and idempotency metadata for multi-worker progressive syncs.

Variant and media behavior

  • A product may have no variants. Send variants_complete: true with variants: [].
  • If variants appear later, keep the same product ID and send the new variant list.
  • Size-only variants normally share product media.
  • Color, pattern, material, and style variants can reference distinct media.
  • Shared media is stored and prepared once even when several variants reference it.
  • A swatch image represents the selector. Variant media represents the garment used for display and try-on.
virtual.fit recommends at most one result per product. A result may identify the best exact variant or the best visual choice within the product. When fresh inventory is known, exact variant results must be available. When availability is unknown, virtual.fit does not claim that a variant is in stock.

Visual choices

You do not create presentation IDs. virtual.fit derives visual choices from option meaning, swatches, and variant media. Use:
  • presentation_role: "include" when an option changes the visible garment.
  • presentation_role: "exclude" for size, fit, length, and other non-visual choices.
  • presentation_role: "auto" when virtual.fit should infer the behavior.
If variant media clearly changes with an option such as color, virtual.fit can infer that the option is visual. Explicit roles remain useful when source media is incomplete or ambiguous.

Size charts

Use one chart without applies_to when it applies to every variant. Use a selector when petite, regular, tall, or another option value uses a different chart. A chart may contain:
  • A public url.
  • Extracted structured content.
  • Both a URL and structured content.
If you omit size metadata, virtual.fit preserves the source size values but does not guess their geographic system, audience, or category. These three fields are independent: for example, us + womens + footwear is different from us + youth + footwear. Petite, regular, and tall remain option values such as fit, and applies_to selects the chart for each fit. Reusing the same chart URL or stable external_id across products allows virtual.fit to share the stored chart document while keeping each product’s applies_to selector.

Optional review evidence

You do not need to send reviews. virtual.fit can collect public review evidence when it prepares a product. If your backend already receives complete review records, you can sync them after creating the product. The optional review endpoint accepts each review’s stars, full text, purchased variant, customer photos or videos, and source-reported measurements or fit votes. virtual.fit analyzes review text asynchronously, so review enrichment never blocks the product from becoming ready. Use a stable source review ID whenever one exists. Send each review as its complete current record so removing media or structured evidence is unambiguous. See Sync product reviews. The storefront can request the compact fit summary for fast product display and load full paginated reviews only when the shopper asks to inspect the evidence.

Partial updates and clearing data

For an existing product:
  • An omitted field stays unchanged.
  • An explicit null clears a supported field or collection.
  • variants_complete: true makes the supplied variant list authoritative.
  • A plain partial variant update does not remove omitted variants.
You may clear handle, preview_image_url, brand, description, product_type, prices, availability, rating, review count, custom instructions, images, options, variants, size charts, garment measurements, or model observations.
Clearing options removes your supplied labels and swatches. If active variants remain, virtual.fit retains the minimum option structure required to describe them.

Order updates from multiple workers

Add ingest metadata when several workers may update one product or when events may arrive out of order. The event and sequence fields make the complete update idempotent and ordered.

Delete catalog data

Use DELETE when the product should be removed from the synced catalog. This permanently removes the synced product record and its managed product images:
The canonical catalog retains a deletion tombstone so a stale source snapshot cannot serve the product again. Syncing the same product ID later creates it again and clears the tombstone.
Use the enable-state endpoint when you only want to hide a product temporarily or preserve its diagnostic history. Deletion removes the synced record and managed images.
To keep the product and its images while removing it from the fitting room, set its enabled state:
Send {"enabled":true} to re-enable it. Disabled products remain in the product count, but do not consume enabled-product slots. Delete one variant:
The variant path accepts the stable source variant ID used during sync.

CSV format

Each CSV upload is a synchronous import of at most 1,000 rows. Split larger catalogs into multiple files. Product and variant upserts are idempotent, so it is safe to retry a file; if an infrastructure failure occurs after processing starts, rows already saved remain saved.
Omit schema_version; version 2 is the default. Repeat the product ID on each variant row. Blank product-level cells on later rows inherit the first row for that product.

Legacy JSON compatibility

Use an explicit legacy version only while an existing image-only integration is being migrated:
Do not add current fields to a version 1 request. If virtual.fit detects fields such as options, variants, prices, inventory, or size charts, it returns a message that lists the incompatible fields and tells you to omit schema_version.

Image requirements

Image URLs must be reachable without shopper cookies, expiring browser sessions, or IP-bound authorization. Use stable HTTPS CDN URLs and clear, high-resolution JPEG, PNG, or WebP images up to 64 MB. Avoid short-lived signed URLs unless they remain available during preparation and later refreshes. Prefer images that show the complete sold product on a model or mannequin. When available, send front, back, and side views. These views provide a more useful fit reference than a flat lay or isolated ghost image and generally produce more accurate try-on results. Flat-lay, ghost, and product-only images are still accepted. virtual.fit automatically analyzes, deduplicates, and selects the strongest prepared views without modifying the originals. When a photo contains several garments, also include a view where the sold item is unambiguous.

Input limits

Limits are intentionally generous enough for large catalogs while preventing a single malformed request from consuming unbounded memory or database space. Limits apply equally to JSON and CSV values. A request that exceeds a byte or collection limit returns 413 with the field that must be reduced. Invalid values within the limits return 400.

Common sync failures

Never call the management API from browser JavaScript. Its API key can modify catalog data and must remain server-side.