OV25

🖼️ Product Cutout Images

Stable public image URLs on images.orbital.vision that always resolve to the latest generated cutout for a product and variant combination, at any size you ask for.

Every cutout image OV25 generates for your catalogue gets a stable, human-readable public URL on images.orbital.vision. The URL never changes - when the underlying image is re-rendered (new model, new materials, quality improvements), the same URL simply starts redirecting to the new file. Use these URLs directly in <img> tags, product feeds, emails, or anywhere else you need product imagery.

https://images.orbital.vision/{account}/{image-key}.webp

A real example:

https://images.orbital.vision/darlings-of-chelsea/galloway~galloway~default.webp

These URLs are public and unauthenticated - no API key goes in the URL. The first path segment identifies your account by name, and everything after it identifies the image.

The easy way: every generated image's exact URL can be copied from your dashboard - open the Products page, open the Product setup panel, and browse the generated cutout images. Use the copied URL as-is. The rest of this page explains how the URL is structured so you can also construct them programmatically.


URL structure

1. The account segment

The first segment is your organization name, slugified:

  • lowercase, accents removed
  • & becomes and
  • hyphens, underscores, and slashes are treated as spaces
  • all other punctuation is dropped
  • spaces become single hyphens

So "Darlings of Chelsea"darlings-of-chelsea, and "Smith & Sons Ltd."smith-and-sons-ltd.

2. The image key

The canonical key joins the range, product, and each variant selection with a tilde (~), each segment slugified with the same rules as above:

{range}~{product}~{variant}~{variant}.webp
  • Variant segments are the selection names of the options that vary for that product (for example a fabric and a wood finish), in the order shown in the dashboard.
  • Products whose images don't vary by option use default as the single variant segment.
  • The .webp extension is optional - .png and .jpg spellings are also accepted (the served file is WebP either way).
  • Slashes work in place of tildes, so range/product/variant.webp resolves too.
  • Matching is case-insensitive and URL-encoding is handled for you.

How a URL is resolved

When a request comes in, the resolver works through these steps:

  1. Exact match - the key is compared against the canonical paths of your generated images (ignoring case, extension, and tilde-vs-slash differences). A hit redirects immediately.
  2. Interpreted match - the key is split into segments and tried as range/product/variants, product/variants, and variants only. Each segment is matched against range names, product names, variant selection names, and their SKUs - so a key built from your own SKU codes can resolve as well.
  3. Fuzzy match - near-miss spellings and partial names are tolerated and scored. The best-scoring ready image wins, provided it clears a minimum confidence; otherwise the request is a 404.

This means you don't have to reproduce our slugs perfectly - reasonable names or SKUs for the range, product, and variants will usually land on the right image. That said, exact canonical keys (or URLs copied from the dashboard) are always the safest.

The response

A successful lookup returns a 307 redirect to the current rendered file - a transparent-background WebP cutout on our CDN. Two debug headers ride along:

HeaderMeaning
X-Org-Auto-Cutout-AssetThe ID of the image the URL resolved to.
X-Org-Auto-Cutout-MatchHow it matched: exact-output-path, range-product-variants, product-variants, or variants.

Redirects are cached at the edge for a few minutes, so a re-render or catalogue change shows up in your storefront quickly without hammering the resolver.

Never store the redirected CDN URL. It points at a specific rendered file and goes stale whenever the image is re-generated. Store and render the images.orbital.vision URL - following the redirect is the browser's job.

Errors

Failed lookups return JSON with an error message and a code:

StatusCodeMeaning
404invalid_image_pathThe path is missing the account or image segment.
404organization_not_foundThe first segment didn't match any account name.
404image_not_foundNothing ready matched the key with enough confidence.

Images can disappear when a product, range, or variant is discontinued - if a URL that used to work starts returning 404, hide that image in your storefront rather than showing a broken image.


Image sizes

Full-size cutouts are big: a typical one is 1920 x 1080 and over a megabyte. Add ?w= to any images.orbital.vision URL and you get a resized, re-compressed copy instead, generated on demand and then cached at our edge:

https://images.orbital.vision/darlings-of-chelsea/galloway~galloway~default.webp?w=400

That single parameter takes the example above from 1.1 MB of PNG to 7.6 KB of WebP, with transparency intact.

Available widths

?w=Typical use
50Tiny swatch dots and pickers
150Swatch grids, basket line items
250Small product tiles
400Product cards, mobile galleries
720Content images, tablet galleries
800Standard desktop product images
1080Large product images
1450Hero and zoom imagery

These eight widths are the complete list. They are fixed rather than free-form because every distinct width is cached separately at the edge: a finite set stays warm and fast for everyone, whereas arbitrary widths would mean a cold render on almost every request.

What you get back

  • Width only. Height follows the source image's aspect ratio, so ?w=400 on a 1920 x 1080 cutout returns 400 x 225. There is no cropping, and no height parameter.
  • Always WebP, whatever the source format was, with transparency preserved.
  • Nothing else is read. h, format, quality and friends are ignored.

An unrecognised width is safe, not broken. Ask for ?w=300 or ?w=2000 and you simply get the full-size original back instead of an error. That is deliberate - a typo costs you bandwidth, never a broken image on a live storefront. It also means a URL that quietly returns something huge is worth double-checking against the table above.

Responsive images

Because the widths are stable and public, they drop straight into a srcset:

<img
  src="https://images.orbital.vision/darlings-of-chelsea/galloway~galloway~default.webp?w=720"
  srcset="https://images.orbital.vision/darlings-of-chelsea/galloway~galloway~default.webp?w=400   400w,
          https://images.orbital.vision/darlings-of-chelsea/galloway~galloway~default.webp?w=720   720w,
          https://images.orbital.vision/darlings-of-chelsea/galloway~galloway~default.webp?w=1080 1080w,
          https://images.orbital.vision/darlings-of-chelsea/galloway~galloway~default.webp?w=1450 1450w"
  sizes="(max-width: 600px) 100vw, 720px"
  alt="Galloway sofa"
/>

The older ?size= parameter

?size=small, ?size=medium and ?size=large are an earlier spelling of widths 50, 150 and 250. They still work and will keep working. Prefer ?w= in new integrations - it reaches the larger sizes too. If both are present, ?w= wins.


Fabric and material images

The same host also serves the flat swatch render of any material in your catalogue - the fabric or finish shot the configurator shows in its material picker:

https://images.orbital.vision/{account}/materials/{material}

A real example:

https://images.orbital.vision/darlings-of-chelsea/materials/claret

Use these for swatch grids, basket line items ("Claret, Dark Oak"), order confirmations, and anywhere else you list a chosen material as a picture rather than a word. No file extension is needed, and selections/ works in place of materials/ if that reads better in your code.

Matching a material

The resolver works down the same kind of ladder as the cutout keys:

  1. Exact name - the path is compared against the material names in your catalogue, ignoring case, punctuation, and hyphen-versus-underscore-versus-space differences.
  2. Option and name - a two-part path is read as {option}/{material}, so materials/fabric/claret disambiguates a name that appears under more than one option.
  3. Fuzzy - near-misses are scored, and the best match wins if it clears a minimum confidence. Long descriptive paths work: materials/stain_resistant_viscose_cotten_claret lands on the same image as materials/claret, misspelling included.

Where a name appears on several products, the most-used one wins, so you get the material's canonical swatch rather than an arbitrary copy of it.

The response

A hit is a 307 redirect to the swatch render, with two debug headers:

HeaderMeaning
X-Org-Selection-ThumbnailThe material name the path resolved to.
X-Org-Selection-MatchHow it matched: exact-name, option-and-name, or fuzzy-name.

Misses return the same { "error": …, "code": … } JSON shape as cutouts, with 404 codes invalid_selection_path, organization_not_found, or selection_not_found.

?w= and ?size= behave exactly as described above, so a swatch grid can ask for ?w=150 and never download a full-resolution fabric shot:

https://images.orbital.vision/darlings-of-chelsea/materials/claret?w=150

Only materials on your account's live, published products resolve. A fabric that has been withdrawn stops resolving, so treat a 404 here the same way as a 404 on a cutout.


Looking up URLs programmatically (JSON API)

If you're building an integration and want the match metadata - or want to verify a match before publishing it - there's an authenticated JSON endpoint that runs the same resolver but returns the result instead of redirecting:

GET https://app.orbital.vision/api/product-cutouts?image={image-key}
Authorization: Bearer {privateApiKey}

This is where your API key comes in. Use a Private Api Key, generated at app.orbital.vision/auth/api-keys - note this is a different key type from the Product Configurator Access key used for embeds, and it's a secret: call this endpoint from your server, not the browser.

curl -H "Authorization: Bearer YOUR_PRIVATE_API_KEY" \
  "https://app.orbital.vision/api/product-cutouts?image=fabian~hatton~chair-small~watson-silver~dark-oak"

A successful response:

{
  "url": "https://…/….webp",
  "image": {
    "id": "…",
    "format": "webp",
    "outputPath": "fabian~hatton~chair-small~watson-silver~dark-oak.webp",
    "status": "ready",
    "readyAt": "2026-06-30T…",
    "updatedAt": "…",
    "createdAt": "…"
  },
  "matched": {
    "inputPath": "fabian~hatton~chair-small~watson-silver~dark-oak",
    "canonicalOutputPath": "fabian~hatton~chair-small~watson-silver~dark-oak.webp",
    "strategy": "exact-output-path",
    "confidence": 100,
    "range": { "name": "Fabian", "rangeId": 123 },
    "product": { "name": "Hatton", "productId": 456 },
    "variants": [ { "optionName": "Fabric", "selectionName": "Watson Silver" },  ]
  }
}

matched.strategy and matched.confidence tell you how the resolver got there - an exact-output-path at confidence 100 is a canonical hit; lower-confidence fuzzy matches may be worth reviewing. url here is the direct CDN file, which is fine for immediate use but subject to the same staleness warning as above - persist the public images.orbital.vision form instead.

Errors follow the same { "error": …, "code": … } shape: 400 for a missing/garbled key or image parameter (missing_api_key, invalid_api_key_format, missing_image), 401 for a key that doesn't authenticate (invalid_api_key), and 404 (image_not_found) when nothing matched.


Behaviour notes

  • Only generated, ready images resolve. Images still queued or rendering for the first time 404 until they're done; once an image exists, re-renders swap seamlessly behind the same URL.
  • Which products and variants get cutout images - and how many - is controlled from the Product setup panel in your dashboard, subject to your account's image allowance.
  • URLs resolve within a single account's images: the account segment scopes the search, so keys only ever match your own catalogue.
  • The public resolver and the JSON API share the same matching logic - a key that works on one works on the other.