SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%

Connectors: Bonhams, Christie's, Sotheby's, Catawiki auction results + shared category mapper (agent I)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed 17 days ago (Sep 7, 2026) parent 995d373

22 changed files +8,303 −28

added connectors/api/_auction-lib/categories.test.ts +36 −0
@@ -0,0 +1,36 @@
1 +import { describe, expect, it } from 'vitest';
2 +import { hintFromLabel, isBundleTitle, slugFromTitle, watchBrand, watchReference } from './categories.js';
3 +
4 +describe('auction category mapping', () => {
5 + it('watch departments', () => {
6 + expect(slugFromTitle('ROLEX. A STAINLESS STEEL WRISTWATCH REF. 16610 SUBMARINER', 'watches')).toBe('rolex');
7 + expect(slugFromTitle('Patek Philippe Nautilus 5711/1A-010', 'watches')).toBe('patek_philippe');
8 + expect(slugFromTitle('Audemars Piguet Royal Oak 15202ST', 'watches')).toBe('audemars_piguet');
9 + expect(slugFromTitle('Omega Speedmaster Professional 145.022', 'watches')).toBe('omega');
10 + expect(slugFromTitle('Hermès Birkin 35 Togo', 'watches')).toBe('luxury_handbags');
11 + expect(slugFromTitle('A diamond and platinum ring, 2.01 carats', 'watches')).toBe('jewelry');
12 + expect(slugFromTitle('Montblanc Meisterstück fountain pen 149', 'watches')).toBe('pens');
13 + expect(watchBrand('CARTIER TANK LOUIS').brand).toBe('Cartier');
14 + expect(watchReference('Ref. 5711/1A-010')).toBe('5711/1A-010');
15 + });
16 + it('labels → hints', () => {
17 + expect(hintFromLabel('Wines & Spirits')).toBe('wine');
18 + expect(hintFromLabel('Coins, Medals and Banknotes')).toBe('coins');
19 + expect(hintFromLabel('Designer Handbags & Fashion')).toBe('handbags');
20 + expect(hintFromLabel('Popular Culture')).toBe('popular_culture');
21 + expect(hintFromLabel('Science and Natural History')).toBe('natural_history');
22 + expect(hintFromLabel('Sneakers, Streetwear & Modern Collectables')).toBe('fashion');
23 + expect(hintFromLabel('Random Department')).toBe('unknown');
24 + });
25 + it('keyword sweeps and honesty', () => {
26 + expect(slugFromTitle('LEGO 10179 Millennium Falcon UCS sealed', 'toys')).toBe('lego_sets');
27 + expect(slugFromTitle('Funko Pop! Marvel #01', 'toys')).toBe('funko');
28 + expect(slugFromTitle('Nike Air Jordan 1 Chicago 1985', 'fashion')).toBe('sneakers');
29 + expect(slugFromTitle('1999 Pokémon Base Set Charizard PSA 10', 'popular_culture')).toBe('pokemon');
30 + expect(slugFromTitle('Amazing Spider-Man #300 CGC 9.8', 'popular_culture')).toBe('marvel_comics');
31 + expect(slugFromTitle('Apollo 11 flown mission patch', 'popular_culture')).toBe('space');
32 + expect(slugFromTitle('Untitled abstract composition', 'unknown')).toBeNull();
33 + expect(isBundleTitle('A collection of 45 coins')).toBe(true);
34 + expect(isBundleTitle('1 sovereign 1912')).toBe(false);
35 + });
36 +});
added connectors/api/_auction-lib/categories.ts +344 −0
@@ -0,0 +1,344 @@
1 +/**
2 + * Shared taxonomy mapping for auction-house connectors (Bonhams, Christie's, Sotheby's, Catawiki).
3 + * Houses describe lots by department/category labels; we map label + title keywords to RareIndex
4 + * taxonomy slugs (data/taxonomy/categories.json). When nothing matches we return null and the
5 + * connector decides whether to keep the lot under a family slug or skip it — never invent attributes.
6 + */
7 +
8 +const WATCH_BRANDS: Array<[RegExp, string, string]> = [
9 + [/\brolex\b/i, 'rolex', 'Rolex'],
10 + [/\bpatek\b/i, 'patek_philippe', 'Patek Philippe'],
11 + [/\baudemars\b|\bap royal oak\b/i, 'audemars_piguet', 'Audemars Piguet'],
12 + [/\bomega\b/i, 'omega', 'Omega'],
13 + [/\brichard mille\b/i, 'other_watches', 'Richard Mille'],
14 + [/\bvacheron\b/i, 'other_watches', 'Vacheron Constantin'],
15 + [/\bcartier\b/i, 'other_watches', 'Cartier'],
16 + [/\btudor\b/i, 'other_watches', 'Tudor'],
17 + [/\bbreitling\b/i, 'other_watches', 'Breitling'],
18 + [/\biwc\b/i, 'other_watches', 'IWC'],
19 + [/\bjaeger[- ]lecoultre\b|\bjlc\b/i, 'other_watches', 'Jaeger-LeCoultre'],
20 + [/\blange\b/i, 'other_watches', 'A. Lange & Söhne'],
21 + [/\bbreguet\b/i, 'other_watches', 'Breguet'],
22 + [/\bblancpain\b/i, 'other_watches', 'Blancpain'],
23 + [/\bzenith\b/i, 'other_watches', 'Zenith'],
24 + [/\bgrand seiko\b/i, 'other_watches', 'Grand Seiko'],
25 + [/\bseiko\b/i, 'other_watches', 'Seiko'],
26 + [/\btag heuer\b|\bheuer\b/i, 'other_watches', 'TAG Heuer'],
27 + [/\bpanerai\b/i, 'other_watches', 'Panerai'],
28 + [/\bhublot\b/i, 'other_watches', 'Hublot'],
29 + [/\bf\.?\s?p\.?\s?journe\b/i, 'other_watches', 'F.P. Journe'],
30 + [/\bmb&f\b/i, 'other_watches', 'MB&F'],
31 + [/\bde bethune\b/i, 'other_watches', 'De Bethune'],
32 + [/\bgreubel\b/i, 'other_watches', 'Greubel Forsey'],
33 + [/\burwerk\b/i, 'other_watches', 'Urwerk'],
34 + [/\blongines\b/i, 'other_watches', 'Longines'],
35 + [/\bpiaget\b/i, 'other_watches', 'Piaget'],
36 + [/\bchopard\b/i, 'other_watches', 'Chopard'],
37 + [/\bvan cleef\b/i, 'other_watches', 'Van Cleef & Arpels'],
38 + [/\bbulgari\b|\bbvlgari\b/i, 'other_watches', 'Bulgari'],
39 + [/\bgirard[- ]perregaux\b/i, 'other_watches', 'Girard-Perregaux'],
40 + [/\bulysse nardin\b/i, 'other_watches', 'Ulysse Nardin'],
41 + [/\bfranck muller\b/i, 'other_watches', 'Franck Muller'],
42 + [/\bbaume\b/i, 'other_watches', 'Baume & Mercier'],
43 +];
44 +
45 +export function watchBrand(title: string): { slug: string; brand: string | null } {
46 + for (const [re, slug, brand] of WATCH_BRANDS) if (re.test(title)) return { slug, brand };
47 + return { slug: 'other_watches', brand: null };
48 +}
49 +
50 +/** Rolex-style reference numbers ("Ref. 116500LN", "REF 5711/1A-010", "126610LN"). */
51 +export function watchReference(title: string): string | null {
52 + const m = title.match(/\b(?:ref(?:erence)?\.?\s*)([0-9]{3,6}[A-Z]{0,4}(?:[\/-][0-9A-Z]{1,6}){0,3})\b/i) ?? title.match(/\b([0-9]{5,6}(?:[A-Z]{1,3}|\/[0-9A-Z]{1,6}))\b/);
53 + return m ? m[1]!.toUpperCase() : null;
54 +}
55 +
56 +const HANDBAG = /\b(birkin|kelly|constance|hermès|hermes|chanel|louis vuitton|goyard|handbag|clutch|tote|mini bag|shoulder bag|pochette)\b/i;
57 +const SNEAKER = /\b(sneaker|air jordan|nike|yeezy|dunk|adidas|new balance|air max|off-white x)\b/i;
58 +const CARD = /\b(trading card|pokémon|pokemon|charizard|psa \d|bgs \d|cgc \d|topps|panini|upper deck|rookie card|magic: the gathering|yu-gi-oh)/i;
59 +const COMIC = /\b(comic|#\d+\s*\(|amazing spider-man|detective comics|action comics|x-men|batman #|superman #|cgc|cbcs)\b/i;
60 +const COMIC_STRONG = /\b(comic|amazing spider-man|detective comics|action comics|x-men #|batman #|superman #|incredible hulk #|fantastic four #|avengers #|spawn #)/i;
61 +const LEGO = /\blego\b/i;
62 +const FUNKO = /\bfunko\b|\bpop!\b/i;
63 +const VINYL = /\b(vinyl|lp record|acetate|test pressing|78 rpm|shellac)\b/i;
64 +const POSTER = /\b(poster|one[- ]sheet|lobby card|affiche)\b/i;
65 +const GUITAR = /\b(guitar|stratocaster|telecaster|les paul|gibson|fender|bass guitar|synthesizer|moog)\b/i;
66 +const PROP = /\b(screen[- ]used|prop|costume|worn by|production[- ]used|film-used|movie-used)\b/i;
67 +const AUTOGRAPH = /\b(signed|autograph|inscribed|hand-signed)\b/i;
68 +const JERSEY = /\b(jersey|game[- ]worn|match[- ]worn|match[- ]issued|game[- ]used|championship ring|olympic (?:gold|silver|bronze) medal|boxing gloves|signed ball|cricket bat|football boots)\b/i;
69 +const COIN = /\b(coin|sovereign|guinea|denarius|aureus|stater|tetradrachm|solidus|ducat|thaler|dollar 18|morgan|double eagle|mint state|pcgs|ngc|ms6\d|ms7\d|au5\d|proof)\b/i;
70 +const BANKNOTE = /\b(banknote|bank note|treasury note|currency note|specimen note|\bnote\b.*\bbank\b)/i;
71 +const MEDAL = /\b(medal|order of|decoration|campaign group|dso|mc group|victoria cross)\b/i;
72 +const STAMP = /\b(stamp|postal|cover|philatel|penny black|inverted)\b/i;
73 +const WHISKY = /\b(whisky|whiskey|bourbon|macallan|springbank|bowmore|ardbeg|yamazaki|hibiki|karuizawa|glenfiddich|dalmore|laphroaig|brora|port ellen)\b/i;
74 +const COGNAC = /\b(cognac|armagnac|calvados)\b/i;
75 +const RUM = /\b(rum|rhum)\b/i;
76 +const WINE = /\b(bottle|bottles|magnum|jeroboam|imperial|bordeaux|burgundy|champagne|château|chateau|domaine|romanée|romanee|petrus|lafite|latour|margaux|mouton|krug|dom pérignon|dom perignon|barolo|brunello|napa|screaming eagle|rhône|rhone|sauternes|port\b|vintage 19|vintage 20|cases? of \d|\d+\s*bts?\b|\bowc\b|\boc\b)/i;
77 +const FOSSIL = /\b(fossil|ammonite|trilobite|dinosaur|tooth|skull|megalodon|mammoth|skeleton)\b/i;
78 +const METEORITE = /\b(meteorite|pallasite|chondrite|lunar|martian)\b/i;
79 +const MINERAL = /\b(mineral|specimen|quartz|amethyst|tourmaline|fluorite|azurite|malachite|geode|crystal cluster|agate)\b/i;
80 +const MAP = /\b(map|atlas|globe|chart of|plan of)\b/i;
81 +const MANUSCRIPT = /\b(manuscript|letter signed|autograph letter|document signed|typed letter|archive of)\b/i;
82 +const CAMERA = /\b(leica|hasselblad|rolleiflex|camera|lens|nikon f|contax)\b/i;
83 +const CAR = /\b(coupe|coupé|roadster|cabriolet|convertible|saloon|sedan|spyder|spider|berlinetta|gt\b|chassis no|vin\b|ferrari|porsche|lamborghini|bentley|aston martin|jaguar|mercedes-benz|bugatti|maserati|alfa romeo|mclaren)\b/i;
84 +const MOTORCYCLE = /\b(motorcycle|motorbike|ducati|harley|triumph|norton|vincent|brough superior|bsa|moto guzzi|frame no)\b/i;
85 +const AUTOMOBILIA = /\b(mascot|badge|enamel sign|petrol pump|steering wheel|racing helmet|race suit|programme|dashboard|hood ornament)\b/i;
86 +const TOY = /\b(tin toy|tinplate|dinky|corgi|matchbox|hot wheels|teddy|steiff|barbie|action figure|star wars figure|transformers|he-man|g\.i\. joe|playmobil|doll\b)\b/i;
87 +const MODEL_CAR = /\b(1:18|1:43|1:64|1:24|diecast|die-cast|autoart|cmc|minichamps|kyosho)\b/i;
88 +const MODEL_TRAIN = /\b(märklin|marklin|hornby|lionel|bachmann|locomotive|gauge)\b/i;
89 +const VIDEO_GAME = /\b(nintendo|sega|playstation|xbox|game boy|gameboy|atari|sealed game|wata|vga \d|nes\b|snes\b|n64\b|famicom)\b/i;
90 +const JEWEL = /\b(ring|necklace|bracelet|brooch|earrings|pendant|diamond|sapphire|ruby|emerald|carat|cts?\b|tiara|van cleef|graff|harry winston|tiffany)\b/i;
91 +const GEMSTONE = /\b(unmounted|loose diamond|loose stone|gia certified|gia report|rough diamond|natural pearl)\b/i;
92 +const PEN = /\b(fountain pen|montblanc|namiki|pelikan|ballpoint|rollerball)\b/i;
93 +const LIGHTER = /\b(lighter|dunhill|zippo|s\.t\. dupont)\b/i;
94 +const PERFUME = /\b(perfume|parfum|fragrance|eau de)\b/i;
95 +const CLOCK = /\b(clock|chronometer|regulator|longcase|bracket clock|carriage clock)\b/i;
96 +const SILVER = /\b(silver|sterling|silver-gilt|vermeil|tea service|flatware|salver|tankard)\b/i;
97 +const GLASS = /\b(glass|lalique|baccarat|murano|daum|gallé|galle|crystal vase|paperweight)\b/i;
98 +const PORCELAIN = /\b(porcelain|meissen|sèvres|sevres|wedgwood|royal copenhagen|worcester|ceramic|earthenware|stoneware|faience|majolica|delft)\b/i;
99 +const SCI = /\b(microscope|telescope|sextant|astrolabe|orrery|barometer|slide rule|calculating|theodolite|octant)\b/i;
100 +const TYPEWRITER = /\btypewriter\b/i;
101 +const MILITARIA = /\b(helmet|uniform|bayonet|sword|dagger|insignia|regiment|militaria|flintlock|musket|cannon|armour|armor|epaulette)\b/i;
102 +const SPACE = /\b(apollo|nasa|space shuttle|flown|astronaut|cosmonaut|soyuz|gemini mission|mercury mission|lunar module)\b/i;
103 +const AVIATION = /\b(aircraft|aviation|propeller|cockpit|spitfire|concorde|airline)\b/i;
104 +const PHOTO = /\b(gelatin silver|photograph|silver print|c-print|chromogenic|platinum print|daguerreotype|albumen)\b/i;
105 +const CONTEMPORARY = /\b(banksy|kaws|murakami|hirst|koons|kusama|basquiat|haring|warhol|richter|hockney|kapoor|kiefer|condo|nara|stik|invader)\b/i;
106 +const ART = /\b(oil on canvas|oil on panel|acrylic on canvas|watercolour|watercolor|gouache|lithograph|screenprint|etching|engraving|woodcut|sculpture|bronze|drawing|pastel|ink on paper|mixed media|print\b|edition of)\b/i;
107 +const BOOK = /\b(first edition|first printing|edition|volumes|vols?\.|folio|octavo|quarto|bound|binding|signed copy|incunabula|hardback|hardcover|dust[- ]?jacket)\b/i;
108 +const ANIMATION = /\b(animation cel|production cel|celluloid|disney studio|storyboard|concept art)\b/i;
109 +const CHESS = /\b(chess set|chessmen|chess board)\b/i;
110 +const ANTIQUE_FURNITURE = /\b(commode|chair|table|cabinet|bureau|chest of drawers|armchair|mirror|console|settee|sofa|desk|bookcase|sideboard|screen|tapestry|carpet|rug)\b/i;
111 +const DESIGN = /\b(eames|prouvé|prouve|perriand|jeanneret|nakashima|noguchi|wegner|jacobsen|panton|memphis|sottsass|knoll|cassina|vitra|mid-century|scandinavian design)\b/i;
112 +
113 +/** Map a title to a slug given a loose department hint. Returns null when no confident match. */
114 +export function slugFromTitle(title: string, hint: DeptHint = 'unknown'): string | null {
115 + const t = title;
116 + // Highly specific signals first (independent of hint)
117 + if (LEGO.test(t)) return 'lego_sets';
118 + if (FUNKO.test(t)) return 'funko';
119 + if (SNEAKER.test(t) && !/\bposter\b/i.test(t)) return 'sneakers';
120 + if (METEORITE.test(t)) return 'meteorites';
121 + if (hint === 'watches' || (/\b(wristwatch|watch|chronograph|pocket watch|tourbillon)\b/i.test(t) && hint !== 'jewelry')) {
122 + if (HANDBAG.test(t) && !/\bwatch|chronograph|wristwatch\b/i.test(t)) return 'luxury_handbags';
123 + if (PEN.test(t) && !/\bwatch\b/i.test(t)) return 'pens';
124 + if (LIGHTER.test(t) && !/\bwatch\b/i.test(t)) return 'lighters';
125 + if (CLOCK.test(t) && !/\bwatch\b/i.test(t)) return 'clocks';
126 + if (JEWEL.test(t) && !/\bwatch|chronograph|wristwatch\b/i.test(t)) return 'jewelry';
127 + return watchBrand(t).slug;
128 + }
129 + if (hint === 'handbags' || HANDBAG.test(t)) return 'luxury_handbags';
130 + if (hint === 'jewelry') return GEMSTONE.test(t) ? 'gemstones' : 'jewelry';
131 + if (hint === 'wine') {
132 + if (WHISKY.test(t)) return 'whisky';
133 + if (COGNAC.test(t)) return 'cognac';
134 + if (RUM.test(t)) return 'rum';
135 + return 'wine';
136 + }
137 + if (WHISKY.test(t)) return 'whisky';
138 + if (COGNAC.test(t)) return 'cognac';
139 + if (hint === 'coins') {
140 + if (BANKNOTE.test(t)) return 'banknotes';
141 + if (MEDAL.test(t) && !COIN.test(t)) return 'medals';
142 + return 'coins';
143 + }
144 + if (hint === 'stamps' || STAMP.test(t) && hint === 'books') return 'stamps';
145 + if (hint === 'cars') return MOTORCYCLE.test(t) ? 'motorcycles' : AUTOMOBILIA.test(t) && !CAR.test(t) ? 'automotive_memorabilia' : 'automobiles';
146 + if (hint === 'motorcycles') return 'motorcycles';
147 + if (hint === 'automobilia') return 'automotive_memorabilia';
148 + if (hint === 'comics' || COMIC_STRONG.test(t)) {
149 + if (ANIMATION.test(t)) return 'animation_art';
150 + if (/\b(marvel|spider-man|x-men|avengers|hulk|fantastic four|iron man|captain america|thor|wolverine|daredevil)\b/i.test(t)) return 'marvel_comics';
151 + if (/\b(dc comics|batman|superman|detective comics|action comics|wonder woman|flash|green lantern)\b/i.test(t)) return 'dc_comics';
152 + if (/\b(manga|tankobon|shonen jump)\b/i.test(t)) return 'manga';
153 + return 'independent_comics';
154 + }
155 + if (hint === 'cards' || CARD.test(t)) {
156 + if (/pok[eé]mon/i.test(t)) return 'pokemon';
157 + if (/magic: the gathering|\bmtg\b/i.test(t)) return 'magic_the_gathering';
158 + if (/yu-gi-oh/i.test(t)) return 'yugioh';
159 + if (/one piece/i.test(t)) return 'one_piece_card_game';
160 + if (/lorcana/i.test(t)) return 'disney_lorcana';
161 + if (/\b(basketball|nba|jordan|lebron|kobe)\b/i.test(t)) return 'basketball_cards';
162 + if (/\b(baseball|mlb|mantle|ruth|topps 195|bowman 195)\b/i.test(t)) return 'baseball_cards';
163 + if (/\b(football|nfl|brady|mahomes)\b/i.test(t)) return 'football_cards';
164 + if (/\b(hockey|nhl|gretzky|mcdavid)\b/i.test(t)) return 'hockey_cards';
165 + if (/\b(soccer|messi|ronaldo|mbapp|prizm world cup|panini fifa)\b/i.test(t)) return 'soccer_cards';
166 + if (/\b(f1|formula 1|verstappen|hamilton)\b/i.test(t)) return 'f1_cards';
167 + return hint === 'cards' ? 'other_tcg' : 'non_sport_cards';
168 + }
169 + if (COMIC.test(t) && !CARD.test(t)) return /\b(marvel|spider-man|x-men|avengers|hulk)\b/i.test(t) ? 'marvel_comics' : /\b(batman|superman|dc comics)\b/i.test(t) ? 'dc_comics' : 'independent_comics';
170 + if (hint === 'popular_culture' || hint === 'entertainment') {
171 + if (GUITAR.test(t)) return 'musical_instruments';
172 + if (VINYL.test(t)) return 'music';
173 + if (POSTER.test(t)) return 'movie_posters';
174 + if (ANIMATION.test(t)) return 'animation_art';
175 + if (PROP.test(t)) return 'movie_memorabilia';
176 + if (VIDEO_GAME.test(t)) return 'video_games';
177 + if (TOY.test(t)) return 'vintage_toys';
178 + if (SPACE.test(t)) return 'space';
179 + if (JERSEY.test(t)) return 'sports_memorabilia';
180 + if (/\b(beatles|rolling stones|bowie|elvis|hendrix|queen|pink floyd|led zeppelin|tour|concert|gold disc|platinum disc|setlist|lyrics)\b/i.test(t)) return 'music_memorabilia';
181 + if (/\b(star wars|harry potter|james bond|007|marvel|disney|lord of the rings|batman|indiana jones|jurassic|back to the future)\b/i.test(t)) return 'movie_memorabilia';
182 + if (AUTOGRAPH.test(t)) return 'autographs';
183 + return 'movie_memorabilia';
184 + }
185 + if (hint === 'sports' || JERSEY.test(t)) return 'sports_memorabilia';
186 + if (hint === 'toys') {
187 + if (MODEL_TRAIN.test(t)) return 'model_trains';
188 + if (MODEL_CAR.test(t)) return 'model_cars';
189 + if (VIDEO_GAME.test(t)) return 'video_games';
190 + if (/\b(action figure|hot toys|sideshow|figuarts|nendoroid|mafex)\b/i.test(t)) return 'action_figures';
191 + if (/\b(doll|barbie|blythe|bisque)\b/i.test(t)) return 'dolls';
192 + if (/\b(plush|teddy|steiff|jellycat)\b/i.test(t)) return 'plush';
193 + if (/\b(bearbrick|kaws|medicom|labubu|pop mart|kidrobot)\b/i.test(t)) return 'designer_toys';
194 + return 'vintage_toys';
195 + }
196 + if (hint === 'natural_history') {
197 + if (FOSSIL.test(t)) return 'fossils';
198 + if (MINERAL.test(t)) return 'minerals';
199 + return 'fossils';
200 + }
201 + if (hint === 'science') return SCI.test(t) ? 'scientific_instruments' : TYPEWRITER.test(t) ? 'typewriters' : FOSSIL.test(t) ? 'fossils' : MINERAL.test(t) ? 'minerals' : 'scientific_instruments';
202 + if (hint === 'books') {
203 + if (MAP.test(t)) return 'maps';
204 + if (MANUSCRIPT.test(t)) return 'historical_documents';
205 + if (PHOTO.test(t)) return 'photography';
206 + return 'books';
207 + }
208 + if (hint === 'photographs') return PHOTO.test(t) || !ART.test(t) ? 'photography' : 'art';
209 + if (hint === 'prints') return CONTEMPORARY.test(t) ? 'contemporary_art' : 'art';
210 + if (hint === 'contemporary') return 'contemporary_art';
211 + if (hint === 'art') return CONTEMPORARY.test(t) ? 'contemporary_art' : PHOTO.test(t) ? 'photography' : 'art';
212 + if (hint === 'clocks') return 'clocks';
213 + if (hint === 'silver') return 'silver';
214 + if (hint === 'glass') return 'glass_crystal';
215 + if (hint === 'ceramics') return 'porcelain';
216 + if (hint === 'militaria') return MEDAL.test(t) ? 'medals' : 'militaria';
217 + if (hint === 'design') return 'design_furniture';
218 + if (hint === 'furniture' || hint === 'decorative') {
219 + if (CLOCK.test(t)) return 'clocks';
220 + if (SILVER.test(t)) return 'silver';
221 + if (GLASS.test(t)) return 'glass_crystal';
222 + if (PORCELAIN.test(t)) return 'porcelain';
223 + if (DESIGN.test(t)) return 'design_furniture';
224 + if (CHESS.test(t)) return 'chess';
225 + return 'antiques';
226 + }
227 + if (hint === 'cameras' || CAMERA.test(t)) return 'cameras';
228 + if (hint === 'music') return GUITAR.test(t) ? 'musical_instruments' : VINYL.test(t) ? 'music' : 'music_memorabilia';
229 + if (hint === 'movies') return POSTER.test(t) ? 'movie_posters' : PROP.test(t) ? 'movie_memorabilia' : ANIMATION.test(t) ? 'animation_art' : 'movie_memorabilia';
230 + if (hint === 'space') return 'space';
231 + if (hint === 'aviation') return AVIATION.test(t) ? 'aviation' : 'space';
232 + if (hint === 'perfume') return 'perfume';
233 + if (hint === 'pens') return PEN.test(t) ? 'pens' : LIGHTER.test(t) ? 'lighters' : 'pens';
234 + if (hint === 'fashion') return HANDBAG.test(t) ? 'luxury_handbags' : SNEAKER.test(t) ? 'sneakers' : 'fashion_streetwear';
235 + if (hint === 'video_games') return 'video_games';
236 + if (hint === 'asian' || hint === 'tribal' || hint === 'antiquities') return 'antiques';
237 + // No hint: broad keyword sweep
238 + if (WINE.test(t) && /\b(19|20)\d{2}\b/.test(t)) return 'wine';
239 + if (COIN.test(t)) return 'coins';
240 + if (STAMP.test(t)) return 'stamps';
241 + if (JEWEL.test(t)) return 'jewelry';
242 + if (CAR.test(t) && /\b(19|20)\d{2}\b/.test(t)) return 'automobiles';
243 + if (VINYL.test(t)) return 'music';
244 + if (POSTER.test(t)) return 'movie_posters';
245 + if (GUITAR.test(t)) return 'musical_instruments';
246 + if (VIDEO_GAME.test(t)) return 'video_games';
247 + if (FOSSIL.test(t)) return 'fossils';
248 + if (MINERAL.test(t)) return 'minerals';
249 + if (MAP.test(t)) return 'maps';
250 + if (BOOK.test(t)) return 'books';
251 + if (PHOTO.test(t)) return 'photography';
252 + if (CONTEMPORARY.test(t)) return 'contemporary_art';
253 + if (ART.test(t)) return 'art';
254 + if (CLOCK.test(t)) return 'clocks';
255 + if (SILVER.test(t)) return 'silver';
256 + if (PORCELAIN.test(t)) return 'porcelain';
257 + if (GLASS.test(t)) return 'glass_crystal';
258 + if (SCI.test(t)) return 'scientific_instruments';
259 + if (MILITARIA.test(t)) return 'militaria';
260 + if (ANTIQUE_FURNITURE.test(t)) return 'antiques';
261 + return null;
262 +}
263 +
264 +export type DeptHint =
265 + | 'unknown' | 'watches' | 'handbags' | 'jewelry' | 'wine' | 'coins' | 'stamps' | 'cars' | 'motorcycles' | 'automobilia' | 'cards' | 'comics'
266 + | 'popular_culture' | 'entertainment' | 'sports' | 'toys' | 'natural_history' | 'science' | 'books' | 'photographs' | 'prints' | 'contemporary' | 'art'
267 + | 'clocks' | 'silver' | 'glass' | 'ceramics' | 'militaria' | 'design' | 'furniture' | 'decorative' | 'cameras' | 'music' | 'movies' | 'space' | 'aviation'
268 + | 'perfume' | 'pens' | 'fashion' | 'video_games' | 'asian' | 'tribal' | 'antiquities';
269 +
270 +/** Map a free-text department / category label from any house to a DeptHint. */
271 +export function hintFromLabel(label: string | null | undefined): DeptHint {
272 + if (!label) return 'unknown';
273 + const l = label.toLowerCase();
274 + if (/watch|horolog/.test(l)) return 'watches';
275 + if (/handbag|luggage/.test(l)) return 'handbags';
276 + if (/jewel|gem/.test(l)) return 'jewelry';
277 + if (/wine|whisky|spirit|champagne/.test(l)) return 'wine';
278 + if (/coin|numismat|banknote|medal/.test(l)) return 'coins';
279 + if (/stamp|philatel|postal/.test(l)) return 'stamps';
280 + if (/motor ?car|\bcars\b|automobile|motoring/.test(l)) return 'cars';
281 + if (/motorcycle/.test(l)) return 'motorcycles';
282 + if (/automobilia/.test(l)) return 'automobilia';
283 + if (/trading card|sports card|pokémon|pokemon|tcg/.test(l)) return 'cards';
284 + if (/comic|animation/.test(l)) return 'comics';
285 + if (/popular culture|entertainment|rock|pop memorabilia|film memorabilia|music memorabilia/.test(l)) return 'popular_culture';
286 + if (/sport/.test(l)) return 'sports';
287 + if (/toy|model|doll|teddy/.test(l)) return 'toys';
288 + if (/natural history|fossil|mineral|meteorite/.test(l)) return 'natural_history';
289 + if (/scien|instrument|technology/.test(l)) return 'science';
290 + if (/book|manuscript|map|atlas|travel|exploration|library/.test(l)) return 'books';
291 + if (/photograph/.test(l)) return 'photographs';
292 + if (/print|multiple|edition/.test(l)) return 'prints';
293 + if (/contemporary|post-war|modern british|20th|21st|street art|urban art/.test(l)) return 'contemporary';
294 + if (/impressionist|old master|painting|fine art|\bart\b|drawing|sculpture|picture/.test(l)) return 'art';
295 + if (/clock|barometer/.test(l)) return 'clocks';
296 + if (/silver|vertu|objects of vertu/.test(l)) return 'silver';
297 + if (/glass|paperweight/.test(l)) return 'glass';
298 + if (/ceramic|porcelain|pottery/.test(l)) return 'ceramics';
299 + if (/arms|armour|armor|militar|medal/.test(l)) return 'militaria';
300 + if (/design/.test(l)) return 'design';
301 + if (/furniture|interiors|decorative|works of art|house sale|carpet|rug|tapestr/.test(l)) return 'furniture';
302 + if (/camera/.test(l)) return 'cameras';
303 + if (/music|instrument|guitar/.test(l)) return 'music';
304 + if (/movie|film|cinema|poster/.test(l)) return 'movies';
305 + if (/space|nasa/.test(l)) return 'space';
306 + if (/aviation|aeronautic/.test(l)) return 'aviation';
307 + if (/perfume|fragrance/.test(l)) return 'perfume';
308 + if (/pen|writing instrument|lighter/.test(l)) return 'pens';
309 + if (/fashion|sneaker|streetwear|couture|accessor/.test(l)) return 'fashion';
310 + if (/video ?game/.test(l)) return 'video_games';
311 + if (/asian|chinese|japanese|islamic|indian|himalayan|korean/.test(l)) return 'asian';
312 + if (/tribal|african|oceanic|native american|pre-columbian/.test(l)) return 'tribal';
313 + if (/antiquit|ancient/.test(l)) return 'antiquities';
314 + return 'unknown';
315 +}
316 +
317 +export function brandFromSlug(slug: string, title: string): string | null {
318 + if (['rolex', 'patek_philippe', 'audemars_piguet', 'omega', 'other_watches'].includes(slug)) return watchBrand(title).brand;
319 + if (slug === 'luxury_handbags') {
320 + const m = title.match(/\b(herm[èe]s|chanel|louis vuitton|dior|gucci|goyard|fendi|bottega veneta|prada|celine|loewe|saint laurent)\b/i);
321 + return m ? m[1]!.replace(/^herm[èe]s$/i, 'Hermès') : null;
322 + }
323 + if (slug === 'lego_sets') return 'LEGO';
324 + if (slug === 'funko') return 'Funko';
325 + return null;
326 +}
327 +
328 +/** "PSA 10", "CGC 9.8" etc. are handled by @rareindex/taxonomy; this extracts a LEGO set number. */
329 +export function legoSetNumber(title: string): string | null {
330 + const m = title.match(/\b(\d{4,5})(?:-1)?\b/);
331 + return m ? m[1]! : null;
332 +}
333 +
334 +export function isBundleTitle(title: string): boolean {
335 + return /\b(collection of|group of|lot of|assorted|quantity of|\(\d{2,}\)|\d{2,}\s*(?:items|pieces|cards|bottles|coins)|set of \d{2,}|mixed lot|various)\b/i.test(title);
336 +}
337 +
338 +export function safeYear(title: string): number | null {
339 + const now = new Date().getUTCFullYear();
340 + const m = title.match(/\b(1[5-9]\d{2}|20\d{2})\b/);
341 + if (!m) return null;
342 + const y = Number(m[1]);
343 + return y <= now ? y : null;
344 +}
added connectors/api/_auction-lib/smoke.ts +57 −0
@@ -0,0 +1,57 @@
1 +/**
2 + * Live smoke + fixture capture for the auction-house connectors.
3 + * Usage: pnpm tsx connectors/api/_auction-lib/smoke.ts <connectorId> [--limit N] [--seed URL]... [--category slug]... [--capture name]
4 + * Requires FIRECRAWL_API_KEY / SCRAPFLY_API_KEY in the environment for the engines the connector uses.
5 + */
6 +import { createCrawlContext, createRouter, getConnectorMeta, loadConnector } from '@rareindex/connectors';
7 +import { saveFixture } from '@rareindex/connectors/testing';
8 +import { childLogger } from '@rareindex/shared';
9 +
10 +const [id, ...rest] = process.argv.slice(2);
11 +if (!id) throw new Error('usage: smoke.ts <connectorId> [--limit N] [--seed URL] [--category slug] [--capture name]');
12 +const opt = { limit: 12, seeds: [] as string[], categories: [] as string[], capture: null as string | null };
13 +for (let i = 0; i < rest.length; i++) {
14 + const a = rest[i]!;
15 + if (a === '--limit') opt.limit = Number(rest[++i]);
16 + else if (a === '--seed') opt.seeds.push(rest[++i]!);
17 + else if (a === '--category') opt.categories.push(rest[++i]!);
18 + else if (a === '--capture') opt.capture = rest[++i]!;
19 +}
20 +
21 +const meta = getConnectorMeta(id);
22 +const connector = await loadConnector(id);
23 +const router = createRouter({ firecrawlApiKey: process.env.FIRECRAWL_API_KEY, scrapflyApiKey: process.env.SCRAPFLY_API_KEY });
24 +const ctx = createCrawlContext({
25 + router,
26 + meta,
27 + options: { mode: 'probe', limit: opt.limit, ...(opt.seeds.length ? { seeds: opt.seeds } : {}), ...(opt.categories.length ? { categories: opt.categories } : {}) },
28 + log: childLogger({ connector: id, smoke: true }),
29 +});
30 +
31 +let rawCount = 0;
32 +let total = 0;
33 +const kinds: Record<string, number> = {};
34 +let captured = 0;
35 +for await (const raw of connector.crawl(ctx)) {
36 + rawCount++;
37 + const rawLike = { ...raw, externalId: raw.externalId ?? null, fetchedAt: raw.fetchedAt ?? new Date() };
38 + const records = await connector.normalize(rawLike);
39 + total += records.length;
40 + for (const r of records) kinds[r.kind] = (kinds[r.kind] ?? 0) + 1;
41 + const p = raw.payload as { lots?: unknown[]; kind?: string };
42 + console.log(`raw#${rawCount} ${raw.kind} ${raw.url} → payload.${p.kind} lots=${p.lots?.length ?? '-'} → ${records.length} records`);
43 + for (const r of records.slice(0, 2)) console.log(JSON.stringify(r, null, 1).slice(0, 1800));
44 + if (opt.capture && captured < 3 && records.length) {
45 + const name = `${opt.capture}-${captured + 1}`;
46 + const first = records[0]!;
47 + saveFixture(id, name, {
48 + raw: { ...rawLike, payload: JSON.parse(JSON.stringify(rawLike.payload)) },
49 + expect: { minCount: 1, kinds: [...new Set(records.map((r) => r.kind))], first: { kind: first.kind, ...('auctionHouse' in first ? { auctionHouse: (first as { auctionHouse: string }).auctionHouse } : {}), ...('currency' in first && first.currency ? { currency: first.currency } : {}) } },
50 + note: `Captured live by connectors/api/_auction-lib/smoke.ts on ${new Date().toISOString().slice(0, 10)} (${records.length} records from this raw page).`,
51 + });
52 + captured++;
53 + console.log(` saved fixture data/fixtures/${id}/${name}.json`);
54 + }
55 + if (rawCount >= 6) break;
56 +}
57 +console.log(JSON.stringify({ rawCount, totalNormalized: total, kinds, engineStats: ctx.engineStats, anomalies: ctx.anomalies }, null, 1));
added connectors/api/bonhams/index.test.ts +84 −0
@@ -0,0 +1,84 @@
1 +import { describe, expect, it } from 'vitest';
2 +import { getConnectorMeta } from '@rareindex/connectors';
3 +import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';
4 +import createConnector, { auctionPageUrl, lotUrl, parseAuctionList, parseAuctionPage, type PagePayload } from './index.js';
5 +import { hintFromLabel, slugFromTitle, watchReference } from '../_auction-lib/categories.js';
6 +
7 +const connector = createConnector(getConnectorMeta('bonhams'));
8 +
9 +describe('bonhams connector', () => {
10 + runFixtureSuite(connector, it, expect);
11 +
12 + it('stores the premium-inclusive price and keeps the hammer', async () => {
13 + const fx = loadFixture('bonhams', 'results-1');
14 + const payload = fx.raw.payload as PagePayload;
15 + const out = await connector.normalize(fx.raw);
16 + const sold = payload.lots.filter((l) => l.status === 'SOLD' && (l.hammerPremium ?? 0) > 0);
17 + expect(out.length).toBe(sold.length);
18 + const lot = sold[0]!;
19 + const rec = out.find((r) => r.kind === 'sale' && r.externalId === `${payload.auction.id}-${lot.lotNo}`);
20 + expect(rec && rec.kind === 'sale').toBe(true);
21 + if (!rec || rec.kind !== 'sale') return;
22 + expect(rec.price).toBe(lot.hammerPremium);
23 + expect(rec.buyerPremiumIncluded).toBe(true);
24 + expect(rec.attributes.metadata.hammer_price).toBe(lot.hammerPrice);
25 + expect(rec.currency).toBe(lot.currency);
26 + expect(rec.saleDate.toISOString()).toBe(new Date(lot.hammerTime!).toISOString());
27 + expect(rec.auctionHouse).toBe('Bonhams');
28 + expect(rec.lotNumber).toBe(lot.lotNo);
29 + expect(rec.sourceUrl).toBe(lotUrl(payload.auction.id, lot.lotNo, lot.slug));
30 + expect(['rolex', 'patek_philippe', 'audemars_piguet', 'omega', 'other_watches']).toContain(rec.attributes.categorySlug);
31 + });
32 +
33 + it('emits auction_lot records for lots that have not ended', async () => {
34 + const fx = loadFixture('bonhams', 'results-1');
35 + const payload = structuredClone(fx.raw.payload) as PagePayload;
36 + const future = new Date(Date.now() + 5 * 86_400_000).toISOString();
37 + payload.auction = { ...payload.auction, isEnded: false, end: future, start: new Date(Date.now() - 86_400_000).toISOString() };
38 + payload.lots = payload.lots.slice(0, 3).map((l) => ({ ...l, status: 'READY', hammerPrice: null, hammerPremium: null, isEnded: false, hammerTime: future, endDate: future }));
39 + const out = await connector.normalize({ ...fx.raw, payload });
40 + expect(out.length).toBe(3);
41 + for (const r of out) {
42 + expect(r.kind).toBe('auction_lot');
43 + if (r.kind !== 'auction_lot') continue;
44 + expect(r.status).toBe('live');
45 + expect(r.estimateLow).not.toBeNull();
46 + expect(r.endsAt?.toISOString()).toBe(new Date(future).toISOString());
47 + }
48 + });
49 +
50 + it('skips unsold, withdrawn and unmapped-department lots', async () => {
51 + const fx = loadFixture('bonhams', 'results-1');
52 + const payload = structuredClone(fx.raw.payload) as PagePayload;
53 + payload.lots = [
54 + { ...payload.lots[0]!, status: 'UNSOLD', hammerPrice: null, hammerPremium: null },
55 + { ...payload.lots[1]!, status: 'WITHDRAWN' },
56 + { ...payload.lots[2]!, department: 'Carpets, Rugs & Tapestries', title: 'A Persian rug' },
57 + payload.lots[3]!,
58 + ];
59 + payload.auction = { ...payload.auction, departments: ['Watches'] };
60 + const out = await connector.normalize({ ...fx.raw, payload });
61 + expect(out.map((r) => ('externalId' in r ? r.externalId : null))).toEqual([`${payload.auction.id}-${payload.lots[3]!.lotNo}`]);
62 + });
63 +
64 + it('parses listing and auction pages defensively', () => {
65 + expect(parseAuctionList('<html></html>')).toEqual({ auctions: [], nbHits: null });
66 + expect(parseAuctionPage('<html></html>')).toBeNull();
67 + expect(auctionPageUrl({ id: '31992', slug: 'weekly-watches' }, 2)).toBe('https://www.bonhams.com/auction/31992/weekly-watches/?page=2');
68 + });
69 +
70 + it('maps departments and titles to taxonomy slugs', () => {
71 + expect(slugFromTitle('ROLEX. A STAINLESS STEEL AUTOMATIC CHRONOGRAPH WRISTWATCH REF 116500LN DAYTONA', hintFromLabel('Watches'))).toBe('rolex');
72 + expect(watchReference('REF 116500LN DAYTONA')).toBe('116500LN');
73 + expect(slugFromTitle('Château Lafite Rothschild 1982 (12 bottles)', hintFromLabel('Wine'))).toBe('wine');
74 + expect(slugFromTitle('The Macallan 25 Year Old Sherry Oak', hintFromLabel('Whisky'))).toBe('whisky');
75 + expect(slugFromTitle('1965 Ferrari 275 GTB Berlinetta Chassis no. 07589', hintFromLabel('Cars'))).toBe('automobiles');
76 + expect(slugFromTitle('Hermès Birkin 30 Togo leather 2019', hintFromLabel('Designer Handbags & Fashion'))).toBe('luxury_handbags');
77 + expect(slugFromTitle('A Gibson Les Paul Standard owned by ...', hintFromLabel('Popular Culture'))).toBe('musical_instruments');
78 + expect(slugFromTitle('Star Wars 1977 original one-sheet poster', hintFromLabel('Popular Culture'))).toBe('movie_posters');
79 + expect(slugFromTitle('Elizabeth II gold sovereign 1958', hintFromLabel('Coins, Medals and Banknotes'))).toBe('coins');
80 + expect(slugFromTitle('Bank of England £5 banknote 1935', hintFromLabel('Coins, Medals and Banknotes'))).toBe('banknotes');
81 + expect(slugFromTitle('A large ammonite fossil, Madagascar', hintFromLabel('Natural History'))).toBe('fossils');
82 + expect(slugFromTitle('Untitled, acrylic on canvas', hintFromLabel('Post-War and Contemporary Art'))).toBe('contemporary_art');
83 + });
84 +});
added connectors/api/bonhams/index.ts +418 −0
@@ -0,0 +1,418 @@
1 +import { z } from 'zod';
2 +import { BaseConnector, type ConnectorMeta, type CrawlContext, type RawRecordInput, type RawRecordLike } from '@rareindex/connectors';
3 +import { NormalizedAuctionLotSchema, NormalizedSaleSchema, type NormalizedRecord, type CurrencyCode, SUPPORTED_CURRENCIES } from '@rareindex/shared';
4 +import { parseGradeFromTitle } from '@rareindex/taxonomy';
5 +import { brandFromSlug, hintFromLabel, isBundleTitle, legoSetNumber, safeYear, slugFromTitle, watchReference } from '../_auction-lib/categories.js';
6 +
7 +/**
8 + * Bonhams — realized prices + upcoming lots from the public, server-rendered Next.js pages.
9 + * Engine: plain HTTPS (no credits). See meta.json accessNotes.
10 + */
11 +
12 +const SITE = 'https://www.bonhams.com';
13 +
14 +export const AuctionSummarySchema = z.object({
15 + id: z.string(),
16 + title: z.string(),
17 + slug: z.string(),
18 + status: z.string().nullable(),
19 + type: z.string().nullable(),
20 + departments: z.array(z.string()),
21 + categories: z.array(z.string()),
22 + currency: z.string().nullable(),
23 + country: z.string().nullable(),
24 + venue: z.string().nullable(),
25 + start: z.string().nullable(),
26 + end: z.string().nullable(),
27 + isEnded: z.boolean(),
28 + numberOfLots: z.number().nullable(),
29 +});
30 +export type AuctionSummary = z.infer<typeof AuctionSummarySchema>;
31 +
32 +export const LotSchema = z.object({
33 + lotId: z.string(),
34 + lotUniqueId: z.string().nullable(),
35 + lotNo: z.string(),
36 + title: z.string(),
37 + heading: z.string().nullable(),
38 + slug: z.string().nullable(),
39 + imageUrl: z.string().nullable(),
40 + estimateLow: z.number().nullable(),
41 + estimateHigh: z.number().nullable(),
42 + hammerPrice: z.number().nullable(),
43 + hammerPremium: z.number().nullable(),
44 + startingBid: z.number().nullable(),
45 + currency: z.string().nullable(),
46 + status: z.string().nullable(),
47 + hammerTime: z.string().nullable(),
48 + endDate: z.string().nullable(),
49 + department: z.string().nullable(),
50 + categories: z.array(z.string()),
51 + isEnded: z.boolean(),
52 + isWithoutReserve: z.boolean().nullable(),
53 +});
54 +export type Lot = z.infer<typeof LotSchema>;
55 +
56 +export const PagePayloadSchema = z.object({
57 + kind: z.literal('auction_lots'),
58 + auction: AuctionSummarySchema,
59 + page: z.number().int(),
60 + nbHits: z.number().nullable(),
61 + lots: z.array(LotSchema),
62 +});
63 +export type PagePayload = z.infer<typeof PagePayloadSchema>;
64 +
65 +const ConfigSchema = z.object({
66 + departments: z.array(z.string()).default([]),
67 + maxResultsPages: z.number().int().min(1).default(20),
68 + maxAuctionsPerRun: z.number().int().min(1).default(40),
69 + upcomingAuctionsPerRun: z.number().int().min(0).default(12),
70 + lotsPerPage: z.number().int().default(48),
71 +});
72 +
73 +type NextData = { props?: { pageProps?: Record<string, unknown> } };
74 +
75 +export function extractNextData(html: string): NextData | null {
76 + const m = html.match(/<script id="__NEXT_DATA__"[^>]*>([\s\S]*?)<\/script>/);
77 + if (!m) return null;
78 + try {
79 + return JSON.parse(m[1]!) as NextData;
80 + } catch {
81 + return null;
82 + }
83 +}
84 +
85 +function str(v: unknown): string | null {
86 + return typeof v === 'string' && v.length ? v : v === null || v === undefined ? null : typeof v === 'number' ? String(v) : null;
87 +}
88 +function numOrNull(v: unknown): number | null {
89 + return typeof v === 'number' && Number.isFinite(v) ? v : null;
90 +}
91 +
92 +/** Summaries from a results/upcoming listing page (pagesOfAuctions) or from an auction page (auction + lots). */
93 +export function parseAuctionList(html: string): { auctions: AuctionSummary[]; nbHits: number | null } {
94 + const nd = extractNextData(html);
95 + const pp = nd?.props?.pageProps ?? {};
96 + const pages = (pp.pagesOfAuctions as unknown[][] | undefined) ?? [];
97 + const auctions: AuctionSummary[] = [];
98 + for (const page of pages) {
99 + for (const a of page as Array<Record<string, any>>) {
100 + const dates = a.dates ?? {};
101 + auctions.push(
102 + AuctionSummarySchema.parse({
103 + id: String(a.id),
104 + title: a.auctionTitle ?? a.auctionHeading ?? '',
105 + slug: a.slug ?? '',
106 + status: str(a.auctionStatus),
107 + type: str(a.auctionType),
108 + departments: ((a.departments as Array<{ name?: string }> | undefined) ?? []).map((d) => d.name ?? '').filter(Boolean),
109 + categories: ((a.categories as Array<{ name?: string }> | undefined) ?? []).map((d) => d.name ?? '').filter(Boolean),
110 + currency: str(a.currency?.iso_code),
111 + country: str(a.country?.code),
112 + venue: str(a.venue ?? a.location?.name),
113 + start: str(dates.start?.datetime),
114 + end: str(dates.end?.datetime ?? a.hammerTime?.datetime),
115 + isEnded: Boolean(a.flags?.isAuctionEnded),
116 + numberOfLots: numOrNull(a.numberOfLots ?? a.number_of_lots),
117 + }),
118 + );
119 + }
120 + }
121 + return { auctions, nbHits: numOrNull(pp.nbHits) };
122 +}
123 +
124 +/** Lots + auction metadata from an auction page (or its _next/data JSON pageProps). */
125 +export function parseAuctionPage(html: string, fallback?: Partial<AuctionSummary>): { auction: AuctionSummary; lots: Lot[]; nbHits: number | null } | null {
126 + const nd = extractNextData(html);
127 + const pp = nd?.props?.pageProps as Record<string, any> | undefined;
128 + if (!pp?.lotData) return null;
129 + const a = pp.auction ?? {};
130 + const rawLots = (pp.lotData.auctionLots as Array<Record<string, any>> | undefined) ?? [];
131 + const first = rawLots[0];
132 + const auction = AuctionSummarySchema.parse({
133 + id: String(first?.auctionId ?? fallback?.id ?? a.iSaleNo ?? ''),
134 + title: a.sSaleName ?? fallback?.title ?? '',
135 + slug: a.slug ?? fallback?.slug ?? '',
136 + status: str(first?.auctionStatus) ?? fallback?.status ?? null,
137 + type: str(first?.auctionType) ?? str(a.sSaleType) ?? fallback?.type ?? null,
138 + departments: ((a.departments as Array<{ sDepartmentName?: string }> | undefined) ?? []).map((d) => d.sDepartmentName ?? '').filter(Boolean),
139 + categories: fallback?.categories ?? [],
140 + currency: str(first?.currency?.iso_code) ?? fallback?.currency ?? null,
141 + country: str(first?.country?.code) ?? fallback?.country ?? null,
142 + venue: str(a.sVenue) ?? fallback?.venue ?? null,
143 + start: str(a.dates?.start?.[0]?.date?.datetime) ?? fallback?.start ?? null,
144 + end: str(a.dates?.end?.datetime) ?? str(first?.auctionEndDate?.datetime) ?? fallback?.end ?? null,
145 + isEnded: Boolean(first?.flags?.isAuctionEnded ?? fallback?.isEnded ?? false),
146 + numberOfLots: numOrNull(a.number_of_lots) ?? fallback?.numberOfLots ?? null,
147 + });
148 + const lots: Lot[] = rawLots.map((l) =>
149 + LotSchema.parse({
150 + lotId: String(l.lotId ?? l.id ?? ''),
151 + lotUniqueId: str(l.lotUniqueId),
152 + lotNo: String(l.lotNo?.full ?? l.lotNo?.number ?? l.lotId ?? ''),
153 + title: String(l.title ?? l.image?.caption ?? '').replace(/\s+/g, ' ').trim(),
154 + heading: str(l.heading) || null,
155 + slug: str(l.slug),
156 + imageUrl: str(l.image?.url),
157 + estimateLow: numOrNull(l.price?.estimateLow),
158 + estimateHigh: numOrNull(l.price?.estimateHigh),
159 + hammerPrice: numOrNull(l.price?.hammerPrice),
160 + hammerPremium: numOrNull(l.price?.hammerPremium),
161 + startingBid: numOrNull(l.price?.startingBidAmount),
162 + currency: str(l.currency?.iso_code),
163 + status: str(l.status),
164 + hammerTime: str(l.hammerTime?.datetime),
165 + endDate: str(l.auctionEndDate?.datetime),
166 + department: str(l.department?.name),
167 + categories: ((l.categories as Array<{ name?: string }> | undefined) ?? []).map((c) => c.name ?? '').filter(Boolean),
168 + isEnded: Boolean(l.flags?.isAuctionEnded),
169 + isWithoutReserve: typeof l.flags?.isWithoutReserve === 'boolean' ? l.flags.isWithoutReserve : null,
170 + }),
171 + );
172 + return { auction, lots, nbHits: numOrNull(pp.lotData.nbHits) };
173 +}
174 +
175 +export function lotUrl(auctionId: string, lotNo: string, slug: string | null): string {
176 + return `${SITE}/auction/${auctionId}/lot/${lotNo}/${slug ? `${slug}/` : ''}`;
177 +}
178 +export function auctionPageUrl(a: { id: string; slug: string }, page: number): string {
179 + return `${SITE}/auction/${a.id}/${a.slug}/${page > 1 ? `?page=${page}` : ''}`;
180 +}
181 +
182 +function currency(code: string | null | undefined): CurrencyCode | null {
183 + return code && (SUPPORTED_CURRENCIES as readonly string[]).includes(code) ? (code as CurrencyCode) : null;
184 +}
185 +
186 +function parseDate(s: string | null | undefined): Date | null {
187 + if (!s) return null;
188 + const d = new Date(s);
189 + return Number.isNaN(d.getTime()) ? null : d;
190 +}
191 +
192 +export default function createConnector(meta: ConnectorMeta) {
193 + return new BonhamsConnector(meta);
194 +}
195 +
196 +export class BonhamsConnector extends BaseConnector {
197 + readonly version = '1.0.0';
198 + readonly parserVersion = '1.0.0';
199 + override readonly urlPatterns = [/^https?:\/\/(www\.)?bonhams\.com\/auction\/\d+\//i];
200 + protected override minIntervalMs = 1500;
201 + private readonly config = ConfigSchema.parse(this.meta.config ?? {});
202 +
203 + private wanted(a: AuctionSummary): boolean {
204 + if (!this.config.departments.length) return true;
205 + return a.departments.some((d) => this.config.departments.includes(d));
206 + }
207 +
208 + private async page(ctx: CrawlContext, url: string): Promise<string | null> {
209 + await this.throttle();
210 + const res = await ctx.fetch(url, { engines: ['api'], responseType: 'text', minQuality: 0, headers: { accept: 'text/html' } });
211 + if (!res.success || !res.html) {
212 + ctx.anomaly('page_fetch_failed', `${url}: ${res.error ?? res.httpStatus}`);
213 + return null;
214 + }
215 + return res.html;
216 + }
217 +
218 + /** Iterate listing pages (results or upcoming) yielding whitelisted auctions until `stop` says so. */
219 + private async *listAuctions(ctx: CrawlContext, path: string, maxPages: number, stop: (a: AuctionSummary) => boolean): AsyncIterable<AuctionSummary> {
220 + for (let page = 1; page <= maxPages; page++) {
221 + const html = await this.page(ctx, `${SITE}${path}${page > 1 ? `?page=${page}` : ''}`);
222 + if (!html) return;
223 + const { auctions } = parseAuctionList(html);
224 + if (!auctions.length) {
225 + if (page === 1) ctx.anomaly('empty_page', `${path}: no auctions parsed (redesign?)`);
226 + return;
227 + }
228 + for (const a of auctions) {
229 + if (stop(a)) return;
230 + if (this.wanted(a)) yield a;
231 + }
232 + }
233 + }
234 +
235 + private async *crawlAuction(ctx: CrawlContext, a: AuctionSummary, kind: 'sale' | 'auction_lot', maxPages = 60): AsyncIterable<RawRecordInput> {
236 + for (let page = 1; page <= maxPages; page++) {
237 + const url = auctionPageUrl(a, page);
238 + const html = await this.page(ctx, url);
239 + if (!html) return;
240 + const parsed = parseAuctionPage(html, a);
241 + if (!parsed) {
242 + ctx.anomaly('parse_failure', `${url}: no lotData in __NEXT_DATA__`);
243 + return;
244 + }
245 + if (!parsed.lots.length) return;
246 + const payload: PagePayload = { kind: 'auction_lots', auction: { ...parsed.auction, categories: a.categories }, page, nbHits: parsed.nbHits, lots: parsed.lots };
247 + yield { url, externalId: `${a.id}#${page}`, kind, engine: 'api', httpStatus: 200, payload, fetchedAt: new Date() };
248 + if (parsed.nbHits !== null && page * this.config.lotsPerPage >= parsed.nbHits) return;
249 + if (ctx.signal?.aborted) return;
250 + }
251 + }
252 +
253 + async *crawl(ctx: CrawlContext): AsyncIterable<RawRecordInput> {
254 + const cursor = { ...(ctx.options.cursor ?? {}) } as { lastEnd?: string; done?: string[] };
255 + const done = new Set(cursor.done ?? []);
256 + const probe = ctx.options.mode === 'probe';
257 + const backfill = ctx.options.mode === 'backfill';
258 + const maxAuctions = probe ? 1 : this.config.maxAuctionsPerRun;
259 + let yielded = 0;
260 + let newestEnd: string | undefined = cursor.lastEnd;
261 + let count = 0;
262 +
263 + // 1. Past results (sold)
264 + const stop = (a: AuctionSummary) => !backfill && !!cursor.lastEnd && !!a.end && a.end < cursor.lastEnd && !probe;
265 + for await (const a of this.listAuctions(ctx, '/auctions/results/', probe ? 1 : this.config.maxResultsPages, stop)) {
266 + if (done.has(a.id)) continue;
267 + if (count >= maxAuctions) break;
268 + count++;
269 + for await (const raw of this.crawlAuction(ctx, a, 'sale', probe ? 1 : 60)) {
270 + yield raw;
271 + yielded += (raw.payload as PagePayload).lots.length;
272 + if (this.reached(ctx, yielded)) return;
273 + }
274 + done.add(a.id);
275 + if (a.end && (!newestEnd || a.end > newestEnd)) newestEnd = a.end;
276 + cursor.done = [...done].slice(-500);
277 + if (!backfill) cursor.lastEnd = newestEnd;
278 + await ctx.setCursor(cursor);
279 + }
280 +
281 + // 2. Upcoming / live lots for the auction calendar (incremental runs only)
282 + if (!probe && !backfill && this.config.upcomingAuctionsPerRun > 0) {
283 + let up = 0;
284 + for await (const a of this.listAuctions(ctx, '/auctions/upcoming/', 3, () => false)) {
285 + if (a.type === 'EXHIBITION') continue;
286 + if (up++ >= this.config.upcomingAuctionsPerRun) break;
287 + for await (const raw of this.crawlAuction(ctx, a, 'auction_lot', 10)) yield raw;
288 + }
289 + }
290 + }
291 +
292 + async lookup(url: string, ctx: CrawlContext): Promise<RawRecordInput[]> {
293 + const m = url.match(/\/auction\/(\d+)\/(?:lot\/(\d+[A-Za-z]?)\/)?([^/?#]*)/);
294 + if (!m) return [];
295 + const auctionId = m[1]!;
296 + const lotNo = m[2];
297 + // The auction page lists lots 48 at a time; find the page containing the lot number when given.
298 + const first = await this.page(ctx, `${SITE}/auction/${auctionId}/`);
299 + if (!first) return [];
300 + const parsed = parseAuctionPage(first);
301 + if (!parsed) return [];
302 + let lots = parsed.lots;
303 + if (lotNo && !lots.some((l) => l.lotNo === lotNo) && parsed.nbHits) {
304 + const pages = Math.ceil(parsed.nbHits / this.config.lotsPerPage);
305 + for (let p = 2; p <= pages; p++) {
306 + const html = await this.page(ctx, auctionPageUrl({ id: auctionId, slug: parsed.auction.slug }, p));
307 + const pg = html ? parseAuctionPage(html, parsed.auction) : null;
308 + if (pg?.lots.some((l) => l.lotNo === lotNo)) {
309 + lots = pg.lots;
310 + break;
311 + }
312 + }
313 + }
314 + if (lotNo) lots = lots.filter((l) => l.lotNo === lotNo);
315 + const payload: PagePayload = { kind: 'auction_lots', auction: parsed.auction, page: 0, nbHits: parsed.nbHits, lots };
316 + return [{ url, externalId: lotNo ? `${auctionId}-${lotNo}` : auctionId, kind: parsed.auction.isEnded ? 'sale' : 'auction_lot', engine: 'api', httpStatus: 200, payload, fetchedAt: new Date() }];
317 + }
318 +
319 + async normalize(raw: RawRecordLike): Promise<NormalizedRecord[]> {
320 + const page = PagePayloadSchema.parse(raw.payload);
321 + const out: NormalizedRecord[] = [];
322 + const a = page.auction;
323 + const observedAt = raw.fetchedAt;
324 + for (const lot of page.lots) {
325 + const dept = lot.department ?? a.departments[0] ?? null;
326 + // A lot's own department is authoritative; fall back to the sale's departments when the lot has none.
327 + if (this.config.departments.length && (dept ? !this.config.departments.includes(dept) : !a.departments.some((d) => this.config.departments.includes(d)))) continue;
328 + const hint = hintFromLabel(dept);
329 + const categorySlug = slugFromTitle(lot.title, hint);
330 + if (!categorySlug) continue; // unmapped department/title → skip rather than guess
331 + const cur = currency(lot.currency ?? a.currency);
332 + if (!cur) continue;
333 + const grade = parseGradeFromTitle(lot.title);
334 + const brand = brandFromSlug(categorySlug, lot.title);
335 + const reference = categorySlug.endsWith('watches') || ['rolex', 'patek_philippe', 'audemars_piguet', 'omega'].includes(categorySlug) ? watchReference(lot.title) : null;
336 + const identifiers: Record<string, string> = { bonhams_lot: `${a.id}-${lot.lotNo}` };
337 + if (lot.lotUniqueId) identifiers.bonhams_lot_unique_id = lot.lotUniqueId;
338 + if (reference) identifiers.reference = reference;
339 + if (categorySlug === 'lego_sets') {
340 + const n = legoSetNumber(lot.title);
341 + if (n) identifiers.lego_set_number = n;
342 + }
343 + const base = {
344 + connectorId: this.meta.id,
345 + sourceId: this.meta.sourceId,
346 + sourceUrl: lotUrl(a.id, lot.lotNo, lot.slug),
347 + externalId: `${a.id}-${lot.lotNo}`,
348 + rawTitle: lot.title,
349 + description: lot.heading,
350 + imageUrls: lot.imageUrl ? [lot.imageUrl] : [],
351 + attributes: {
352 + categorySlug,
353 + name: lot.title,
354 + brand,
355 + reference,
356 + year: safeYear(lot.title),
357 + country: a.country,
358 + identifiers,
359 + metadata: { department: dept, auction_id: a.id, auction_title: a.title, auction_type: a.type, venue: a.venue, estimate_low: lot.estimateLow, estimate_high: lot.estimateHigh, hammer_price: lot.hammerPrice, without_reserve: lot.isWithoutReserve },
360 + },
361 + grade: { grader: grade.grader, grade: grade.grade, qualifier: grade.qualifier, certificationNumber: null },
362 + condition: {},
363 + observedAt,
364 + parserVersion: this.parserVersion,
365 + };
366 + const saleDate = parseDate(lot.hammerTime ?? lot.endDate ?? a.end);
367 + const sold = lot.status === 'SOLD' && (lot.hammerPremium ?? lot.hammerPrice ?? 0) > 0;
368 + const endDate = parseDate(lot.endDate ?? a.end);
369 + const ended = sold || lot.isEnded || a.isEnded || lot.status === 'UNSOLD' || lot.status === 'WITHDRAWN' || (endDate !== null && endDate.getTime() < Date.now());
370 + if (ended) {
371 + // Only published results (status SOLD with a price) become sales; unsold/withdrawn lots are skipped.
372 + if (!sold || !saleDate || saleDate.getTime() > Date.now() + 86_400_000) continue;
373 + const price = lot.hammerPremium ?? lot.hammerPrice!;
374 + out.push(
375 + NormalizedSaleSchema.parse({
376 + ...base,
377 + kind: 'sale',
378 + confidence: 0.9,
379 + saleType: 'auction',
380 + saleDate,
381 + price,
382 + currency: cur,
383 + buyerPremiumIncluded: lot.hammerPremium !== null,
384 + quantity: 1,
385 + isBundle: isBundleTitle(lot.title),
386 + location: a.venue ?? a.country,
387 + auctionHouse: 'Bonhams',
388 + lotNumber: lot.lotNo,
389 + }),
390 + );
391 + } else {
392 + const endsAt = parseDate(lot.endDate ?? a.end);
393 + const startsAt = parseDate(a.start);
394 + const now = Date.now();
395 + const status = startsAt && startsAt.getTime() <= now ? 'live' : 'upcoming';
396 + out.push(
397 + NormalizedAuctionLotSchema.parse({
398 + ...base,
399 + kind: 'auction_lot',
400 + confidence: 0.85,
401 + auctionHouse: 'Bonhams',
402 + auctionName: a.title,
403 + lotNumber: lot.lotNo,
404 + startsAt,
405 + endsAt,
406 + estimateLow: lot.estimateLow,
407 + estimateHigh: lot.estimateHigh,
408 + currentBid: null,
409 + currency: cur,
410 + status,
411 + location: a.venue ?? a.country,
412 + }),
413 + );
414 + }
415 + }
416 + return out;
417 + }
418 +}
added connectors/api/bonhams/meta.json +36 −0
@@ -0,0 +1,36 @@
1 +{
2 + "id": "bonhams",
3 + "displayName": "Bonhams (auction results & upcoming lots)",
4 + "sourceId": "bonhams",
5 + "sourceName": "Bonhams",
6 + "sourceType": "auction_house",
7 + "sourceUrl": "https://www.bonhams.com",
8 + "module": "api/bonhams",
9 + "enginePriority": ["api"],
10 + "categories": ["rolex", "patek_philippe", "audemars_piguet", "omega", "other_watches", "wine", "whisky", "coins", "banknotes", "medals", "automobiles", "motorcycles", "automotive_memorabilia", "luxury_handbags", "fashion_streetwear", "jewelry", "movie_memorabilia", "music_memorabilia", "musical_instruments", "movie_posters", "vintage_toys", "sports_memorabilia", "books", "maps", "photography", "art", "contemporary_art", "clocks", "silver", "glass_crystal", "porcelain", "scientific_instruments", "stamps", "fossils", "minerals", "meteorites", "militaria", "design_furniture", "antiques"],
11 + "regions": ["GB", "US", "HK", "FR", "AU"],
12 + "languages": ["en"],
13 + "currency": ["GBP", "USD", "HKD", "EUR", "AUD", "CHF"],
14 + "supportsListings": false,
15 + "supportsSold": true,
16 + "supportsAuctions": true,
17 + "supportsImages": true,
18 + "supportsCatalog": false,
19 + "supportsPopulation": false,
20 + "supportsLookup": true,
21 + "refreshFrequencyMinutes": 360,
22 + "priority": "high",
23 + "trustScore": 0.9,
24 + "attributionRequired": true,
25 + "termsUrl": "https://www.bonhams.com/legals/terms-of-use/",
26 + "accessNotes": "Plain HTTPS (no rendering, no credits). Public results listing https://www.bonhams.com/auctions/results/?page=N and upcoming listing /auctions/upcoming/ are server-rendered Next.js pages whose __NEXT_DATA__ carries 24 auctions per page (11k+ past auctions); each auction page /auction/<id>/<slug>/?page=N carries 48 lots per page with estimates, hammer price, price including buyer's premium (hammerPremium), status, currency, department and end date. bonhams.com/robots.txt only disallows /ldc/, /vms-assets/, */aggregate$ and */head_image* — none used. Prices: we store hammerPremium (hammer + buyer's premium as published by Bonhams) as the sale price with buyerPremiumIncluded=true and keep the hammer price in metadata. Sale date = the lot's hammerTime / auction end date from the source. Departments outside the configured whitelist are skipped, not guessed.",
27 + "enabled": true,
28 + "schemaVersion": "1.0",
29 + "config": {
30 + "departments": ["Watches", "Wine", "Whisky", "Coins, Medals and Banknotes", "Cars", "Motorcycles", "Automobilia", "Designer Handbags & Fashion", "Jewellery", "Popular Culture", "Sporting Memorabilia", "Books & Manuscripts", "Photographs", "Prints & Multiples", "Post-War and Contemporary Art", "Clocks", "Silver", "Glass", "Scientific Instruments", "Stamps, Covers & Postal History", "Natural History", "Arms and Armour", "Modern Decorative Art & Design", "Impressionist and Modern Art", "Modern British & Irish Art", "European Ceramics", "British Ceramics", "Travel & Exploration", "Home and Interiors"],
31 + "maxResultsPages": 20,
32 + "maxAuctionsPerRun": 40,
33 + "upcomingAuctionsPerRun": 12,
34 + "lotsPerPage": 48
35 + }
36 +}
added connectors/api/christies/index.test.ts +75 −0
@@ -0,0 +1,75 @@
1 +import { describe, expect, it } from 'vitest';
2 +import { getConnectorMeta } from '@rareindex/connectors';
3 +import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';
4 +import createConnector, { currencyFromText, hintForSale, lotSearchUrl, parseLotSearch, parseResultsMonth, resultsUrl, type PagePayload } from './index.js';
5 +
6 +const connector = createConnector(getConnectorMeta('christies'));
7 +
8 +describe('christies connector', () => {
9 + runFixtureSuite(connector, it, expect);
10 +
11 + it('emits one premium-inclusive sale per realised lot, with the source currency and date', async () => {
12 + const fx = loadFixture('christies', 'results-1');
13 + const payload = fx.raw.payload as PagePayload;
14 + const out = await connector.normalize(fx.raw);
15 + const realised = payload.lots.filter((l) => !l.withdrawn && (l.priceRealised ?? 0) > 0);
16 + expect(out.length).toBeGreaterThan(0);
17 + expect(out.length).toBeLessThanOrEqual(realised.length);
18 + for (const r of out) {
19 + expect(r.kind).toBe('sale');
20 + if (r.kind !== 'sale') continue;
21 + const lot = payload.lots.find((l) => l.objectId === r.externalId)!;
22 + expect(r.price).toBe(lot.priceRealised);
23 + expect(r.currency).toBe(currencyFromText(lot.priceRealisedText));
24 + expect(r.buyerPremiumIncluded).toBe(true);
25 + expect(r.saleDate.toISOString()).toBe(new Date(lot.endDate ?? payload.sale.endDate!).toISOString());
26 + expect(r.auctionHouse).toBe("Christie's");
27 + expect(r.lotNumber).toBe(lot.lotNumber);
28 + expect(r.attributes.identifiers.christies_sale_number).toBe(payload.sale.saleNumber);
29 + expect(r.attributes.metadata.estimate_low).toBe(lot.estimateLow);
30 + }
31 + });
32 +
33 + it('skips withdrawn and unsold lots', async () => {
34 + const fx = loadFixture('christies', 'results-1');
35 + const payload = structuredClone(fx.raw.payload) as PagePayload;
36 + const keep = payload.lots.find((l) => (l.priceRealised ?? 0) > 0)!;
37 + payload.lots = [{ ...keep, objectId: 'w', withdrawn: true }, { ...keep, objectId: 'u', priceRealised: null, priceRealisedText: null }, { ...keep, objectId: 'z', priceRealised: 0 }, keep];
38 + const out = await connector.normalize({ ...fx.raw, payload });
39 + expect(out.map((r) => ('externalId' in r ? r.externalId : null))).toEqual([keep.objectId]);
40 + });
41 +
42 + it('parses month results and lot searches', () => {
43 + const month = {
44 + filters: { groups: [{ title_txt: 'Category', type: 'category', filters: [{ id: 'category_9', label_txt: 'Jewellery, Watches & Handbags' }] }] },
45 + events: [{ event_id: '31193', landing_url: 'https://www.christies.com/en/auction/x-31193/', title_txt: 'Important Watches', subtitle_txt: 'Live Auction 24546 | CLOSED', filter_ids: '|category_9|location_36|event_0||event_live|', location_txt: 'London', start_date: '2026-07-08T00:00:00', end_date: '2026-07-08T00:00:00', sale_total_value_txt: 'GBP 12,707,879' }],
46 + };
47 + const sales = parseResultsMonth(month);
48 + expect(sales).toHaveLength(1);
49 + expect(sales[0]).toMatchObject({ saleId: '31193', saleNumber: '24546', eventType: 'Live', categoryLabels: ['Jewellery, Watches & Handbags'], location: 'London' });
50 + expect(hintForSale(sales[0]!, ['Jewellery, Watches & Handbags'])).toBe('watches');
51 + expect(lotSearchUrl(sales[0]!, 2, 84)).toContain('SaleNumber=24546&SaleId=31193&page=2&pageSize=84');
52 + expect(resultsUrl(7, 2026)).toBe('https://www.christies.com/api/discoverywebsite/auctioncalendar/auctionresults?language=en&month=7&year=2026');
53 + const ls = parseLotSearch({ lots: [{ object_id: '1', lot_id_txt: '5', title_primary_txt: 'ROLEX', title_secondary_txt: 'REF. 6239 DAYTONA', price_realised: '190500.0', price_realised_txt: 'GBP 190,500', estimate_low: '40000.0', estimate_high: '60000.0', end_date: '2026-07-07T23:00Z', url: 'https://www.christies.com/en/lot/lot-1' }], total_hits_filtered: 1 });
54 + expect(ls.total).toBe(1);
55 + expect(ls.lots[0]).toMatchObject({ objectId: '1', lotNumber: '5', priceRealised: 190500, estimateLow: 40000 });
56 + expect(currencyFromText('HKD 1,250,000')).toBe('HKD');
57 + expect(currencyFromText(null)).toBeNull();
58 + });
59 +
60 + it('maps a watch lot from a jewellery/watches sale to the brand slug with reference', async () => {
61 + const fx = loadFixture('christies', 'results-1');
62 + const payload = structuredClone(fx.raw.payload) as PagePayload;
63 + payload.sale = { ...payload.sale, categoryLabels: ['Jewellery, Watches & Handbags'], title: 'Important Watches' };
64 + const base = payload.lots.find((l) => (l.priceRealised ?? 0) > 0)!;
65 + payload.lots = [{ ...base, objectId: 'rolex1', titlePrimary: 'ROLEX', titleSecondary: 'REF. 116500LN DAYTONA, A STAINLESS STEEL AUTOMATIC CHRONOGRAPH WRISTWATCH', titleTertiary: null, description: null, priceRealised: 30000, priceRealisedText: 'USD 30,000' }];
66 + const out = await connector.normalize({ ...fx.raw, payload });
67 + expect(out).toHaveLength(1);
68 + const r = out[0]!;
69 + if (r.kind !== 'sale') throw new Error('expected sale');
70 + expect(r.attributes.categorySlug).toBe('rolex');
71 + expect(r.attributes.identifiers.reference).toBe('116500LN');
72 + expect(r.attributes.brand).toBe('Rolex');
73 + expect(r.currency).toBe('USD');
74 + });
75 +});
added connectors/api/christies/index.ts +307 −0
@@ -0,0 +1,307 @@
1 +import { z } from 'zod';
2 +import { BaseConnector, type ConnectorMeta, type CrawlContext, type RawRecordInput, type RawRecordLike } from '@rareindex/connectors';
3 +import { NormalizedSaleSchema, SUPPORTED_CURRENCIES, type CurrencyCode, type NormalizedRecord } from '@rareindex/shared';
4 +import { parseGradeFromTitle } from '@rareindex/taxonomy';
5 +import { brandFromSlug, hintFromLabel, isBundleTitle, legoSetNumber, safeYear, slugFromTitle, watchReference, type DeptHint } from '../_auction-lib/categories.js';
6 +
7 +/**
8 + * Christie's — prices realised from the public discovery-website JSON endpoints (§110).
9 + * Engine: plain HTTPS. See meta.json accessNotes.
10 + */
11 +
12 +const SITE = 'https://www.christies.com';
13 +const RESULTS = `${SITE}/api/discoverywebsite/auctioncalendar/auctionresults`;
14 +const LOTSEARCH = `${SITE}/api/discoverywebsite/auctionpages/lotsearch`;
15 +/** christies.com's edge silently drops requests whose User-Agent contains a URL or '@'; we still identify ourselves honestly. */
16 +const UA = 'RareIndex/0.1 (market data research; contact data at rareindex.io)';
17 +
18 +export const SaleSchema = z.object({
19 + saleId: z.string(),
20 + saleNumber: z.string(),
21 + title: z.string(),
22 + subtitle: z.string().nullable(),
23 + eventType: z.string().nullable(), // Live | Online
24 + location: z.string().nullable(),
25 + startDate: z.string().nullable(),
26 + endDate: z.string().nullable(),
27 + landingUrl: z.string().nullable(),
28 + categoryLabels: z.array(z.string()),
29 + saleTotalText: z.string().nullable(),
30 +});
31 +export type Sale = z.infer<typeof SaleSchema>;
32 +
33 +export const LotSchema = z.object({
34 + objectId: z.string(),
35 + lotNumber: z.string(),
36 + titlePrimary: z.string(),
37 + titleSecondary: z.string().nullable(),
38 + titleTertiary: z.string().nullable(),
39 + description: z.string().nullable(),
40 + url: z.string().nullable(),
41 + imageUrl: z.string().nullable(),
42 + estimateLow: z.number().nullable(),
43 + estimateHigh: z.number().nullable(),
44 + estimateText: z.string().nullable(),
45 + priceRealised: z.number().nullable(),
46 + priceRealisedText: z.string().nullable(),
47 + startDate: z.string().nullable(),
48 + endDate: z.string().nullable(),
49 + withdrawn: z.boolean(),
50 + isOver: z.boolean(),
51 +});
52 +export type Lot = z.infer<typeof LotSchema>;
53 +
54 +export const PagePayloadSchema = z.object({
55 + kind: z.literal('sale_lots'),
56 + sale: SaleSchema,
57 + page: z.number().int(),
58 + totalHits: z.number().nullable(),
59 + lots: z.array(LotSchema),
60 +});
61 +export type PagePayload = z.infer<typeof PagePayloadSchema>;
62 +
63 +const ConfigSchema = z.object({
64 + categoryLabels: z.array(z.string()).default([]),
65 + monthsPerRun: z.number().int().min(1).default(2),
66 + backfillMonths: z.number().int().min(1).default(36),
67 + maxSalesPerRun: z.number().int().min(1).default(30),
68 + pageSize: z.number().int().min(10).max(200).default(84),
69 +});
70 +
71 +function numOrNull(v: unknown): number | null {
72 + if (v === null || v === undefined || v === '') return null;
73 + const n = typeof v === 'number' ? v : Number.parseFloat(String(v));
74 + return Number.isFinite(n) ? n : null;
75 +}
76 +const str = (v: unknown): string | null => (typeof v === 'string' && v.trim().length ? v.trim() : null);
77 +
78 +/** Parse an auctionresults month response into sales; `categoryNames` maps filter ids → labels. */
79 +export function parseResultsMonth(json: any): Sale[] {
80 + const labels = new Map<string, string>();
81 + for (const g of json?.filters?.groups ?? []) {
82 + for (const f of g.filters ?? []) if (f.id && f.label_txt) labels.set(String(f.id), String(f.label_txt));
83 + for (const fg of Object.values((g.filter_groups ?? {}) as Record<string, any>)) for (const f of fg?.filters ?? []) if (f.id && f.label_txt) labels.set(String(f.id), String(f.label_txt));
84 + }
85 + const out: Sale[] = [];
86 + for (const e of json?.events ?? []) {
87 + const landing = str(e.landing_url);
88 + const saleNumber = landing?.match(/SaleNumber=(\d+)/)?.[1] ?? String(e.subtitle_txt ?? '').match(/Auction\s+(\d{4,6})/)?.[1] ?? null;
89 + if (!e.event_id || !saleNumber) continue;
90 + const ids = String(e.filter_ids ?? '').split('|').filter(Boolean);
91 + const categoryLabels = ids.filter((id) => id.startsWith('category_')).map((id) => labels.get(id) ?? id);
92 + const locId = ids.find((id) => id.startsWith('location_'));
93 + out.push(
94 + SaleSchema.parse({
95 + saleId: String(e.event_id),
96 + saleNumber,
97 + title: String(e.title_txt ?? ''),
98 + subtitle: str(e.subtitle_txt),
99 + eventType: /online/i.test(String(e.subtitle_txt ?? '')) || ids.includes('event_115') ? 'Online' : ids.includes('event_live') ? 'Live' : null,
100 + location: str(e.location_txt) ?? (locId ? labels.get(locId) ?? null : null),
101 + startDate: str(e.start_date),
102 + endDate: str(e.end_date),
103 + landingUrl: landing,
104 + categoryLabels,
105 + saleTotalText: str(e.sale_total_value_txt),
106 + }),
107 + );
108 + }
109 + return out;
110 +}
111 +
112 +export function parseLotSearch(json: any): { lots: Lot[]; total: number | null } {
113 + const lots: Lot[] = [];
114 + for (const l of json?.lots ?? []) {
115 + lots.push(
116 + LotSchema.parse({
117 + objectId: String(l.object_id ?? ''),
118 + lotNumber: String(l.lot_id_txt ?? ''),
119 + titlePrimary: String(l.title_primary_txt ?? '').trim(),
120 + titleSecondary: str(l.title_secondary_txt),
121 + titleTertiary: str(l.title_tertiary_txt),
122 + description: str(String(l.description_txt ?? '').replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ')),
123 + url: str(l.url),
124 + imageUrl: str(l.image?.image_src),
125 + estimateLow: numOrNull(l.estimate_low),
126 + estimateHigh: numOrNull(l.estimate_high),
127 + estimateText: str(l.estimate_txt),
128 + priceRealised: numOrNull(l.price_realised),
129 + priceRealisedText: str(l.price_realised_txt),
130 + startDate: str(l.start_date),
131 + endDate: str(l.end_date),
132 + withdrawn: Boolean(l.lot_withdrawn),
133 + isOver: Boolean(l.is_auction_over),
134 + }),
135 + );
136 + }
137 + return { lots, total: numOrNull(json?.total_hits_filtered) };
138 +}
139 +
140 +export function resultsUrl(month: number, year: number): string {
141 + return `${RESULTS}?language=en&month=${month}&year=${year}`;
142 +}
143 +export function lotSearchUrl(sale: Pick<Sale, 'saleId' | 'saleNumber'>, page: number, pageSize: number): string {
144 + return `${LOTSEARCH}?language=en&SaleNumber=${sale.saleNumber}&SaleId=${sale.saleId}&page=${page}&pageSize=${pageSize}&sortby=lotnumber`;
145 +}
146 +
147 +/** "GBP 190,500" → { currency, amount } (amount taken from numeric price_realised when available). */
148 +export function currencyFromText(text: string | null): CurrencyCode | null {
149 + const code = text?.match(/^([A-Z]{3})\b/)?.[1] ?? null;
150 + return code && (SUPPORTED_CURRENCIES as readonly string[]).includes(code) ? (code as CurrencyCode) : null;
151 +}
152 +
153 +export function hintForSale(sale: Sale, cfg: string[]): DeptHint {
154 + const labels = sale.categoryLabels.length ? sale.categoryLabels : [];
155 + const chosen = labels.find((l) => cfg.includes(l)) ?? labels[0] ?? null;
156 + const fromLabel = hintFromLabel(chosen);
157 + if (fromLabel !== 'unknown') return fromLabel;
158 + if (chosen === 'Collectibles') return 'popular_culture';
159 + return hintFromLabel(sale.title);
160 +}
161 +
162 +function monthsBack(from: Date, n: number): Array<{ month: number; year: number }> {
163 + const out: Array<{ month: number; year: number }> = [];
164 + const d = new Date(Date.UTC(from.getUTCFullYear(), from.getUTCMonth(), 1));
165 + for (let i = 0; i < n; i++) {
166 + out.push({ month: d.getUTCMonth() + 1, year: d.getUTCFullYear() });
167 + d.setUTCMonth(d.getUTCMonth() - 1);
168 + }
169 + return out;
170 +}
171 +
172 +export default function createConnector(meta: ConnectorMeta) {
173 + return new ChristiesConnector(meta);
174 +}
175 +
176 +export class ChristiesConnector extends BaseConnector {
177 + readonly version = '1.0.0';
178 + readonly parserVersion = '1.0.0';
179 + protected override minIntervalMs = 1200;
180 + private readonly config = ConfigSchema.parse(this.meta.config ?? {});
181 +
182 + private async json(ctx: CrawlContext, url: string): Promise<unknown | null> {
183 + await this.throttle();
184 + const res = await ctx.fetch(url, { engines: ['api'], responseType: 'json', minQuality: 0, headers: { accept: 'application/json', referer: `${SITE}/en/results`, 'user-agent': UA } });
185 + if (!res.success || res.json === null || res.json === undefined) {
186 + ctx.anomaly('page_fetch_failed', `${url}: ${res.error ?? res.httpStatus}`);
187 + return null;
188 + }
189 + return res.json;
190 + }
191 +
192 + private wanted(sale: Sale): boolean {
193 + if (!this.config.categoryLabels.length) return true;
194 + return sale.categoryLabels.some((l) => this.config.categoryLabels.includes(l));
195 + }
196 +
197 + async *crawl(ctx: CrawlContext): AsyncIterable<RawRecordInput> {
198 + const cursor = { ...(ctx.options.cursor ?? {}) } as { done?: string[]; backfillMonth?: string };
199 + const done = new Set(cursor.done ?? []);
200 + const probe = ctx.options.mode === 'probe';
201 + const backfill = ctx.options.mode === 'backfill';
202 + const now = new Date();
203 + let months = monthsBack(now, probe ? 1 : backfill ? this.config.backfillMonths : this.config.monthsPerRun);
204 + if (backfill && cursor.backfillMonth) {
205 + const [y, m] = cursor.backfillMonth.split('-').map(Number);
206 + months = months.filter((x) => x.year < y! || (x.year === y && x.month <= m!));
207 + }
208 + let sales = 0;
209 + let yielded = 0;
210 + for (const { month, year } of months) {
211 + const monthJson = await this.json(ctx, resultsUrl(month, year));
212 + if (!monthJson) continue;
213 + const list = parseResultsMonth(monthJson).filter((s) => this.wanted(s));
214 + if (!list.length && !(monthJson as { events?: unknown[] }).events?.length) ctx.anomaly('empty_page', `results ${year}-${month}: no events`);
215 + for (const sale of list) {
216 + if (done.has(sale.saleId)) continue;
217 + if (sales >= (probe ? 1 : this.config.maxSalesPerRun)) return;
218 + sales++;
219 + let page = 1;
220 + let seen = 0;
221 + for (; page <= 40; page++) {
222 + const url = lotSearchUrl(sale, page, probe ? 20 : this.config.pageSize);
223 + const lj = await this.json(ctx, url);
224 + if (!lj) break;
225 + const { lots, total } = parseLotSearch(lj);
226 + if (!lots.length) break;
227 + seen += lots.length;
228 + const payload: PagePayload = { kind: 'sale_lots', sale, page, totalHits: total, lots };
229 + yield { url, externalId: `${sale.saleNumber}#${page}`, kind: 'sale', engine: 'api', httpStatus: 200, payload, fetchedAt: new Date() };
230 + yielded += lots.length;
231 + if (this.reached(ctx, yielded)) return;
232 + if (probe || (total !== null && seen >= total)) break;
233 + }
234 + done.add(sale.saleId);
235 + cursor.done = [...done].slice(-800);
236 + await ctx.setCursor(cursor);
237 + }
238 + if (backfill) {
239 + cursor.backfillMonth = `${year}-${String(month).padStart(2, '0')}`;
240 + await ctx.setCursor(cursor);
241 + }
242 + }
243 + }
244 +
245 + async normalize(raw: RawRecordLike): Promise<NormalizedRecord[]> {
246 + const page = PagePayloadSchema.parse(raw.payload);
247 + const sale = page.sale;
248 + const hint = hintForSale(sale, this.config.categoryLabels);
249 + const out: NormalizedRecord[] = [];
250 + for (const lot of page.lots) {
251 + if (lot.withdrawn || lot.priceRealised === null || lot.priceRealised <= 0) continue;
252 + const cur = currencyFromText(lot.priceRealisedText) ?? currencyFromText(lot.estimateText);
253 + if (!cur) continue;
254 + const title = [lot.titlePrimary, lot.titleSecondary, lot.titleTertiary].filter(Boolean).join(' — ');
255 + const categorySlug = slugFromTitle(title, hint) ?? slugFromTitle(lot.description ?? '', hint);
256 + if (!categorySlug) continue;
257 + const saleDate = new Date(lot.endDate ?? sale.endDate ?? '');
258 + if (Number.isNaN(saleDate.getTime()) || saleDate.getTime() > Date.now() + 86_400_000) continue;
259 + const grade = parseGradeFromTitle(title);
260 + const isWatch = ['rolex', 'patek_philippe', 'audemars_piguet', 'omega', 'other_watches'].includes(categorySlug);
261 + const reference = isWatch ? watchReference(`${title} ${lot.description ?? ''}`) : null;
262 + const identifiers: Record<string, string> = { christies_object_id: lot.objectId, christies_sale_number: sale.saleNumber };
263 + if (reference) identifiers.reference = reference;
264 + if (categorySlug === 'lego_sets') {
265 + const n = legoSetNumber(title);
266 + if (n) identifiers.lego_set_number = n;
267 + }
268 + out.push(
269 + NormalizedSaleSchema.parse({
270 + kind: 'sale',
271 + connectorId: this.meta.id,
272 + sourceId: this.meta.sourceId,
273 + sourceUrl: lot.url ?? `${SITE}/en/lot/lot-${lot.objectId}`,
274 + externalId: lot.objectId,
275 + rawTitle: title,
276 + description: lot.description,
277 + imageUrls: lot.imageUrl ? [lot.imageUrl] : [],
278 + attributes: {
279 + categorySlug,
280 + name: lot.titleSecondary && isWatch ? `${lot.titlePrimary} ${lot.titleSecondary}` : title,
281 + brand: brandFromSlug(categorySlug, title) ?? (isWatch ? lot.titlePrimary.replace(/\.$/, '') : null),
282 + reference,
283 + year: safeYear(title),
284 + identifiers,
285 + metadata: { sale_id: sale.saleId, sale_number: sale.saleNumber, sale_title: sale.title, sale_type: sale.eventType, sale_categories: sale.categoryLabels, estimate_low: lot.estimateLow, estimate_high: lot.estimateHigh, estimate_text: lot.estimateText },
286 + },
287 + grade: { grader: grade.grader, grade: grade.grade, qualifier: grade.qualifier, certificationNumber: null },
288 + condition: {},
289 + observedAt: raw.fetchedAt,
290 + confidence: 0.9,
291 + parserVersion: this.parserVersion,
292 + saleType: 'auction',
293 + saleDate,
294 + price: lot.priceRealised,
295 + currency: cur,
296 + buyerPremiumIncluded: true,
297 + quantity: 1,
298 + isBundle: isBundleTitle(title),
299 + location: sale.location,
300 + auctionHouse: "Christie's",
301 + lotNumber: lot.lotNumber,
302 + }),
303 + );
304 + }
305 + return out;
306 + }
307 +}
added connectors/api/christies/meta.json +95 −0
@@ -0,0 +1,95 @@
1 +{
2 + "id": "christies",
3 + "displayName": "Christie's (auction results)",
4 + "sourceId": "christies",
5 + "sourceName": "Christie's",
6 + "sourceType": "auction_house",
7 + "sourceUrl": "https://www.christies.com",
8 + "module": "api/christies",
9 + "enginePriority": [
10 + "api"
11 + ],
12 + "categories": [
13 + "rolex",
14 + "patek_philippe",
15 + "audemars_piguet",
16 + "omega",
17 + "other_watches",
18 + "luxury_handbags",
19 + "jewelry",
20 + "gemstones",
21 + "wine",
22 + "whisky",
23 + "cognac",
24 + "art",
25 + "contemporary_art",
26 + "photography",
27 + "books",
28 + "maps",
29 + "historical_documents",
30 + "antiques",
31 + "design_furniture",
32 + "scientific_instruments",
33 + "fossils",
34 + "minerals",
35 + "meteorites",
36 + "sports_memorabilia",
37 + "movie_memorabilia",
38 + "music_memorabilia",
39 + "sneakers",
40 + "vintage_toys",
41 + "automobiles"
42 + ],
43 + "regions": [
44 + "US",
45 + "GB",
46 + "HK",
47 + "FR",
48 + "CH"
49 + ],
50 + "languages": [
51 + "en"
52 + ],
53 + "currency": [
54 + "USD",
55 + "GBP",
56 + "HKD",
57 + "EUR",
58 + "CHF"
59 + ],
60 + "supportsListings": false,
61 + "supportsSold": true,
62 + "supportsAuctions": false,
63 + "supportsImages": true,
64 + "supportsCatalog": false,
65 + "supportsPopulation": false,
66 + "supportsLookup": false,
67 + "refreshFrequencyMinutes": 720,
68 + "priority": "high",
69 + "trustScore": 0.9,
70 + "attributionRequired": true,
71 + "termsUrl": "https://www.christies.com/en/help/terms-and-conditions",
72 + "accessNotes": "Plain HTTPS JSON (no rendering, no credits) from the two endpoints the public christies.com pages themselves call: /api/discoverywebsite/auctioncalendar/auctionresults?language=en&month=M&year=Y (closed sales of a month with SaleID/SaleNumber, category/location filters and sale totals) and /api/discoverywebsite/auctionpages/lotsearch?language=en&SaleNumber=…&SaleId=…&page=N&pageSize=…&sortby=lotnumber (lots with estimate, price_realised, dates, image, lot url; max ~84 lots per page). christies.com/robots.txt (User-agent: *) disallows */search, */AjaxPages, */lotimages, */mychristies and similar — none of these paths are used. Prices realised are published by Christie's inclusive of buyer's premium → buyerPremiumIncluded=true; currency comes from price_realised_txt (e.g. 'GBP 190,500'); sale date = the lot's end_date. Categories come from the sale's category filter labels plus title keywords; unmapped lots keep the family suggested by the sale category. Upcoming lots are not exposed by these endpoints (calendar of future sales is a different client app), so supportsAuctions=false. Note: christies.com's edge drops requests whose User-Agent contains a URL or an e-mail address, so the connector identifies itself as 'RareIndex/0.1 (market data research; contact data at rareindex.io)' — no browser impersonation.",
73 + "enabled": true,
74 + "schemaVersion": "1.0",
75 + "config": {
76 + "categoryLabels": [
77 + "Jewellery, Watches & Handbags",
78 + "Wines & Spirits",
79 + "Collectibles",
80 + "Books & Manuscripts",
81 + "Science and Natural History",
82 + "Photographs & Prints",
83 + "Fine Art",
84 + "Furniture & Decorative Art",
85 + "Antiquities",
86 + "Asian Art",
87 + "Design",
88 + "Cars"
89 + ],
90 + "monthsPerRun": 2,
91 + "backfillMonths": 36,
92 + "maxSalesPerRun": 30,
93 + "pageSize": 84
94 + }
95 +}
added connectors/api/sothebys/index.test.ts +68 −0
@@ -0,0 +1,68 @@
1 +import { describe, expect, it } from 'vitest';
2 +import { getConnectorMeta } from '@rareindex/connectors';
3 +import { listFixtures, loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';
4 +import createConnector, { auctionLinks, classifyTitle, hintsForAuction, lotUrl, parseAuctionPage, parseGraphqlLots, type PagePayload } from './index.js';
5 +
6 +const connector = createConnector(getConnectorMeta('sothebys'));
7 +
8 +describe('sothebys connector', () => {
9 + runFixtureSuite(connector, it, expect);
10 +
11 + it('closed sales: price includes premium, hammer kept in metadata, date from the lot closing time', async () => {
12 + const closed = listFixtures('sothebys').filter((n) => n.startsWith('closed'));
13 + expect(closed.length).toBeGreaterThan(0);
14 + const fx = loadFixture('sothebys', closed[0]!);
15 + const payload = fx.raw.payload as PagePayload;
16 + expect(payload.auction.state).toBe('Closed');
17 + const out = await connector.normalize(fx.raw);
18 + expect(out.length).toBeGreaterThan(0);
19 + for (const r of out) {
20 + expect(r.kind).toBe('sale');
21 + if (r.kind !== 'sale') continue;
22 + const lot = payload.lots.find((l) => l.lotId === r.externalId)!;
23 + expect(lot.isSold).toBe(true);
24 + expect(r.price).toBe(lot.finalPrice);
25 + expect(r.price).toBeGreaterThanOrEqual(lot.currentBid ?? 0);
26 + expect(r.buyerPremiumIncluded).toBe(true);
27 + expect(r.attributes.metadata.hammer_price).toBe(lot.currentBid);
28 + expect(r.saleDate.toISOString()).toBe(new Date(lot.closingTime ?? payload.auction.closedAt!).toISOString());
29 + expect(r.auctionHouse).toBe("Sotheby's");
30 + expect(r.sourceUrl).toBe(lotUrl(payload.auction.url, lot.slug, lot.lotId));
31 + }
32 + });
33 +
34 + it('open sales: lots become auction_lot records with estimates', async () => {
35 + const live = listFixtures('sothebys').filter((n) => n.startsWith('live'));
36 + expect(live.length).toBeGreaterThan(0);
37 + const fx = loadFixture('sothebys', live[0]!);
38 + const payload = fx.raw.payload as PagePayload;
39 + expect(payload.auction.state).not.toBe('Closed');
40 + const out = await connector.normalize(fx.raw);
41 + expect(out.length).toBeGreaterThan(0);
42 + for (const r of out) {
43 + expect(r.kind).toBe('auction_lot');
44 + if (r.kind !== 'auction_lot') continue;
45 + expect(['upcoming', 'live']).toContain(r.status);
46 + expect(r.currency).toBe(payload.auction.currency);
47 + expect(r.auctionName).toBe(payload.auction.title);
48 + }
49 + });
50 +
51 + it('mixed multi-department sales only trust title keywords', () => {
52 + const mixed = { auctionId: 'x', url: 'u', title: 'Arcade | New York', saleNumber: null, state: 'Closed', type: 'Timed', departments: ['American Furniture', 'Decorative Art', 'American Art', 'Books & Manuscripts', 'Contemporary Art'], currency: 'USD', location: 'New York', startsAt: null, endsAt: null, closedAt: null, totalLots: null };
53 + const hints = hintsForAuction(mixed);
54 + expect(hints[0]).toBe('unknown');
55 + expect(classifyTitle('Tom Baril — Lilies', hints)).toBeNull();
56 + expect(classifyTitle('Andy Warhol — Marilyn, screenprint', hints)).toBe('contemporary_art');
57 + const watches = { ...mixed, title: 'Important Watches', departments: ['Watches'] };
58 + expect(classifyTitle('Patek Philippe — Nautilus Ref. 5711/1A', hintsForAuction(watches))).toBe('patek_philippe');
59 + });
60 +
61 + it('parses GraphQL pages and discovery links defensively', () => {
62 + expect(parseAuctionPage('<html></html>', 'u')).toBeNull();
63 + expect(parseGraphqlLots({ errors: [{ message: 'x' }] })).toBeNull();
64 + const gl = parseGraphqlLots({ data: { auction: { lotCards: { totalCount: 1, hasNextPage: false, lots: [{ lotId: 'l1', title: 'T', lotNumber: { lotDisplayNumber: '7' }, slug: { lotSlug: 't' }, estimateV2: { lowEstimate: { amount: '10' }, highEstimate: { amount: '20' } }, bidState: { isClosed: true, closingTime: '2026-08-26T16:01Z', numberOfBids: 3, currentBidV2: { amount: '900', currency: 'USD' }, sold: { __typename: 'ResultVisible', isSold: true, premiums: { finalPriceV2: { amount: '1152', currency: 'USD' } } } } }] } } } });
65 + expect(gl?.lots[0]).toMatchObject({ lotId: 'l1', lotNumber: '7', estimateLow: 10, currentBid: 900, finalPrice: 1152, finalCurrency: 'USD', isSold: true });
66 + expect(auctionLinks('<a href="https://www.sothebys.com/en/buy/auction/2026/arcade-new-york">x</a> https://www.sothebys.com/en/buy/auction/2026/arcade-new-york/lilies')).toEqual(['https://www.sothebys.com/en/buy/auction/2026/arcade-new-york']);
67 + });
68 +});
added connectors/api/sothebys/index.ts +419 −0
@@ -0,0 +1,419 @@
1 +import { z } from 'zod';
2 +import { BaseConnector, type ConnectorMeta, type CrawlContext, type RawRecordInput, type RawRecordLike } from '@rareindex/connectors';
3 +import { NormalizedAuctionLotSchema, NormalizedSaleSchema, SUPPORTED_CURRENCIES, type CurrencyCode, type NormalizedRecord } from '@rareindex/shared';
4 +import { parseGradeFromTitle } from '@rareindex/taxonomy';
5 +import { brandFromSlug, hintFromLabel, isBundleTitle, legoSetNumber, safeYear, slugFromTitle, watchReference, type DeptHint } from '../_auction-lib/categories.js';
6 +
7 +/**
8 + * Sotheby's — results (price incl. premium) and upcoming lots from the public auction pages and the
9 + * page's own GraphQL lot-card pagination. Engine: plain HTTPS (+ Firecrawl for link discovery).
10 + */
11 +
12 +const SITE = 'https://www.sothebys.com';
13 +const GRAPHQL = 'https://clientapi.prod.sothelabs.com/graphql';
14 +
15 +export const AuctionSchema = z.object({
16 + auctionId: z.string(),
17 + url: z.string(),
18 + title: z.string(),
19 + saleNumber: z.string().nullable(),
20 + state: z.string().nullable(), // Opened | Closed | Published…
21 + type: z.string().nullable(), // Timed | Live
22 + departments: z.array(z.string()),
23 + currency: z.string().nullable(),
24 + location: z.string().nullable(),
25 + startsAt: z.string().nullable(),
26 + endsAt: z.string().nullable(),
27 + closedAt: z.string().nullable(),
28 + totalLots: z.number().nullable(),
29 +});
30 +export type Auction = z.infer<typeof AuctionSchema>;
31 +
32 +export const LotSchema = z.object({
33 + lotId: z.string(),
34 + lotNumber: z.string().nullable(),
35 + title: z.string(),
36 + creators: z.string().nullable(),
37 + slug: z.string().nullable(),
38 + estimateLow: z.number().nullable(),
39 + estimateHigh: z.number().nullable(),
40 + isClosed: z.boolean().nullable(),
41 + closingTime: z.string().nullable(),
42 + currentBid: z.number().nullable(),
43 + bidCurrency: z.string().nullable(),
44 + isSold: z.boolean().nullable(),
45 + finalPrice: z.number().nullable(),
46 + finalCurrency: z.string().nullable(),
47 + numberOfBids: z.number().nullable(),
48 + imageUrl: z.string().nullable(),
49 + withdrawn: z.boolean(),
50 +});
51 +export type Lot = z.infer<typeof LotSchema>;
52 +
53 +export const PagePayloadSchema = z.object({
54 + kind: z.literal('auction_page'),
55 + auction: AuctionSchema,
56 + offset: z.number().int(),
57 + lots: z.array(LotSchema),
58 +});
59 +export type PagePayload = z.infer<typeof PagePayloadSchema>;
60 +
61 +const ConfigSchema = z.object({
62 + seeds: z.array(z.string()).default([]),
63 + discoveryPages: z.array(z.string()).default([]),
64 + departments: z.array(z.string()).default([]),
65 + maxAuctionsPerRun: z.number().int().default(25),
66 + pageSize: z.number().int().min(1).max(48).default(48),
67 +});
68 +
69 +const LOT_QUERY = `query LotCardsFilterByPaginated($id: String!, $limit: Int, $offset: Int) {
70 + auction(id: $id, language: ENGLISH) {
71 + id
72 + lotCards: lotCardsConnection(offset: $offset, limit: $limit, filter: ALL) {
73 + totalCount
74 + hasNextPage
75 + lots {
76 + lotId
77 + title
78 + creatorsDisplayTitle
79 + lotNumber { ... on VisibleLotNumber { lotDisplayNumber } }
80 + slug { lotSlug }
81 + withdrawnState { state }
82 + estimateV2 { ... on LowHighEstimateV2 { lowEstimate { amount } highEstimate { amount } } }
83 + bidState {
84 + isClosed
85 + closingTime
86 + numberOfBids
87 + currentBidV2 { amount currency }
88 + sold { __typename ... on ResultVisible { isSold premiums { finalPriceV2 { amount currency } } } }
89 + }
90 + media(imageSizes: [Small]) { images { renditions { url } } }
91 + }
92 + }
93 + }
94 +}`;
95 +
96 +function num(v: unknown): number | null {
97 + if (v === null || v === undefined || v === '') return null;
98 + const n = typeof v === 'number' ? v : Number.parseFloat(String(v));
99 + return Number.isFinite(n) ? n : null;
100 +}
101 +
102 +/** Build a Lot from a GraphQL lot card or from the SSR Apollo cache (refs resolved by caller). */
103 +function lotFrom(card: Record<string, any>, bidState: Record<string, any> | null): Lot {
104 + const est = card.estimateV2 ?? {};
105 + const sold = bidState?.sold ?? {};
106 + const fp = sold.premiums?.finalPriceV2 ?? null;
107 + const cb = bidState?.currentBidV2 ?? null;
108 + const mediaKey = Object.keys(card).find((k) => k.startsWith('media'));
109 + const img = mediaKey ? card[mediaKey]?.images?.[0]?.renditions?.[0]?.url ?? null : null;
110 + return LotSchema.parse({
111 + lotId: String(card.lotId),
112 + lotNumber: card.lotNumber?.lotDisplayNumber ?? null,
113 + title: String(card.title ?? ''),
114 + creators: card.creatorsDisplayTitle ?? null,
115 + slug: card.slug?.lotSlug ?? null,
116 + estimateLow: num(est.lowEstimate?.amount),
117 + estimateHigh: num(est.highEstimate?.amount),
118 + isClosed: typeof bidState?.isClosed === 'boolean' ? bidState.isClosed : null,
119 + closingTime: bidState?.closingTime ?? null,
120 + currentBid: num(cb?.amount),
121 + bidCurrency: cb?.currency ?? null,
122 + isSold: typeof sold.isSold === 'boolean' ? sold.isSold : null,
123 + finalPrice: num(fp?.amount),
124 + finalCurrency: fp?.currency ?? null,
125 + numberOfBids: num(bidState?.numberOfBids),
126 + imageUrl: typeof img === 'string' ? img : null,
127 + withdrawn: card.withdrawnState?.state ? card.withdrawnState.state !== 'NotAffected' : false,
128 + });
129 +}
130 +
131 +/** Parse an SSR auction page: auction + first lot cards from the Apollo cache. */
132 +export function parseAuctionPage(html: string, url: string): { auction: Auction; lots: Lot[] } | null {
133 + const m = html.match(/<script id="__NEXT_DATA__"[^>]*>([\s\S]*?)<\/script>/);
134 + if (!m) return null;
135 + let cache: Record<string, any>;
136 + let pp: Record<string, any>;
137 + try {
138 + pp = (JSON.parse(m[1]!) as { props: { pageProps: Record<string, any> } }).props.pageProps;
139 + cache = pp.apolloCache ?? {};
140 + } catch {
141 + return null;
142 + }
143 + const aKey = Object.keys(cache).find((k) => k.startsWith('Auction:'));
144 + if (!aKey) return null;
145 + const a = cache[aKey];
146 + const dates = a.dates ?? {};
147 + const cards = Object.keys(cache)
148 + .filter((k) => k.startsWith('LotCard:'))
149 + .map((k) => cache[k])
150 + .filter((c) => !c.auction || c.auction.auctionId === a.auctionId || c.auction.sapSaleNumber === a.sapSaleNumber);
151 + const lots = cards.map((c) => lotFrom(c, c.bidState?.__ref ? cache[c.bidState.__ref] ?? null : c.bidState ?? null));
152 + const currency = a.currencyV2 ?? a.currency ?? cards[0]?.auction?.currency ?? lots.find((l) => l.finalCurrency)?.finalCurrency ?? null;
153 + const auction = AuctionSchema.parse({
154 + auctionId: String(a.auctionId),
155 + url,
156 + title: String(a.title ?? ''),
157 + saleNumber: a.sapSaleNumber ?? null,
158 + state: a.state ?? null,
159 + type: a.type ?? null,
160 + departments: Array.isArray(a.departmentNames) ? a.departmentNames.map((d: string) => d.trim()) : [],
161 + currency,
162 + location: a.locationV2?.name ?? null,
163 + startsAt: dates.goesLive ?? dates.acceptsBids ?? null,
164 + endsAt: dates.startsToClose ?? dates.goesLive ?? null,
165 + closedAt: dates.closed ?? null,
166 + totalLots: num(pp.totalLotCount),
167 + });
168 + return { auction, lots };
169 +}
170 +
171 +export function parseGraphqlLots(json: any): { lots: Lot[]; hasNextPage: boolean; totalCount: number | null } | null {
172 + const conn = json?.data?.auction?.lotCards;
173 + if (!conn) return null;
174 + return { lots: (conn.lots ?? []).map((c: Record<string, any>) => lotFrom(c, c.bidState ?? null)), hasNextPage: Boolean(conn.hasNextPage), totalCount: num(conn.totalCount) };
175 +}
176 +
177 +export function auctionLinks(html: string): string[] {
178 + return [...new Set([...html.matchAll(/https?:\/\/www\.sothebys\.com\/en\/buy\/auction\/(20\d{2})\/([a-z0-9-]+)/g)].map((m) => `${SITE}/en/buy/auction/${m[1]}/${m[2]}`))];
179 +}
180 +
181 +export function lotUrl(auctionUrl: string, lotSlug: string | null, lotId: string): string {
182 + return lotSlug ? `${auctionUrl}/${lotSlug}` : `${auctionUrl}?lotId=${lotId}`;
183 +}
184 +
185 +function currency(code: string | null | undefined): CurrencyCode | null {
186 + return code && (SUPPORTED_CURRENCIES as readonly string[]).includes(code) ? (code as CurrencyCode) : null;
187 +}
188 +
189 +/** Ordered hints for an auction: a single-department sale is a strong hint; a mixed "Arcade"-style sale is not. */
190 +export function hintsForAuction(a: Auction): DeptHint[] {
191 + const hints = a.departments.map((d) => hintFromLabel(d)).filter((h) => h !== 'unknown');
192 + const titleHint = hintFromLabel(a.title);
193 + // Mixed multi-department sales (e.g. "Arcade"): only title keywords are trusted; no department guess.
194 + if (a.departments.length > 3) return ['unknown', ...(titleHint !== 'unknown' ? [titleHint] : [])];
195 + return [...(hints.length ? hints : []), ...(titleHint !== 'unknown' ? [titleHint] : []), 'unknown'];
196 +}
197 +
198 +export function classifyTitle(title: string, hints: DeptHint[]): string | null {
199 + for (const h of hints) {
200 + const slug = slugFromTitle(title, h);
201 + if (slug) return slug;
202 + }
203 + return null;
204 +}
205 +
206 +function iso(d: string | null | undefined): Date | null {
207 + if (!d) return null;
208 + const x = new Date(d);
209 + return Number.isNaN(x.getTime()) ? null : x;
210 +}
211 +
212 +export default function createConnector(meta: ConnectorMeta) {
213 + return new SothebysConnector(meta);
214 +}
215 +
216 +export class SothebysConnector extends BaseConnector {
217 + readonly version = '1.0.0';
218 + readonly parserVersion = '1.0.0';
219 + override readonly urlPatterns = [/^https?:\/\/(www\.)?sothebys\.com\/en\/buy\/auction\/20\d{2}\/[a-z0-9-]+/i];
220 + protected override minIntervalMs = 1500;
221 + private readonly config = ConfigSchema.parse(this.meta.config ?? {});
222 +
223 + private async page(ctx: CrawlContext, url: string): Promise<string | null> {
224 + await this.throttle();
225 + const res = await ctx.fetch(url, { engines: ['api'], responseType: 'text', minQuality: 0, headers: { accept: 'text/html' } });
226 + if (!res.success || !res.html) {
227 + ctx.anomaly('page_fetch_failed', `${url}: ${res.error ?? res.httpStatus}`);
228 + return null;
229 + }
230 + return res.html;
231 + }
232 +
233 + private async graphql(ctx: CrawlContext, auctionId: string, offset: number): Promise<ReturnType<typeof parseGraphqlLots>> {
234 + await this.throttle();
235 + const res = await ctx.fetch(GRAPHQL, {
236 + engines: ['api'],
237 + method: 'POST',
238 + body: { operationName: 'LotCardsFilterByPaginated', query: LOT_QUERY, variables: { id: auctionId, limit: this.config.pageSize, offset } },
239 + headers: { origin: SITE, referer: `${SITE}/`, accept: 'application/json' },
240 + responseType: 'json',
241 + minQuality: 0,
242 + });
243 + if (!res.success || !res.json) {
244 + ctx.anomaly('page_fetch_failed', `graphql ${auctionId}@${offset}: ${res.error ?? res.httpStatus}`);
245 + return null;
246 + }
247 + const parsed = parseGraphqlLots(res.json);
248 + if (!parsed) ctx.anomaly('parse_failure', `graphql ${auctionId}@${offset}: ${JSON.stringify((res.json as { errors?: unknown }).errors ?? '').slice(0, 200)}`);
249 + return parsed;
250 + }
251 +
252 + private async discover(ctx: CrawlContext): Promise<string[]> {
253 + const found = new Set<string>(this.config.seeds);
254 + for (const page of this.config.discoveryPages) {
255 + const res = await ctx.fetch(page, { engines: ['firecrawl'], waitForMs: 4000, minQuality: 0 });
256 + if (!res.success || !res.html) {
257 + ctx.anomaly('page_fetch_failed', `${page}: ${res.error ?? res.httpStatus}`);
258 + continue;
259 + }
260 + for (const u of auctionLinks(res.html)) found.add(u);
261 + }
262 + return [...found];
263 + }
264 +
265 + private async *crawlAuction(ctx: CrawlContext, url: string, probe: boolean): AsyncIterable<RawRecordInput> {
266 + const html = await this.page(ctx, url);
267 + if (!html) return;
268 + const parsed = parseAuctionPage(html, url);
269 + if (!parsed) {
270 + ctx.anomaly('parse_failure', `${url}: no Auction in __NEXT_DATA__`);
271 + return;
272 + }
273 + const a = parsed.auction;
274 + if (this.config.departments.length && !a.departments.some((d) => this.config.departments.includes(d))) return;
275 + const kind = a.state === 'Closed' ? 'sale' : 'auction_lot';
276 + const first: PagePayload = { kind: 'auction_page', auction: a, offset: 0, lots: parsed.lots };
277 + yield { url, externalId: `${a.auctionId}#0`, kind, engine: 'api', httpStatus: 200, payload: first, fetchedAt: new Date() };
278 + if (probe) return;
279 + let offset = parsed.lots.length;
280 + const total = a.totalLots ?? Infinity;
281 + for (let guard = 0; offset < total && guard < 60; guard++) {
282 + const gl = await this.graphql(ctx, a.auctionId, offset);
283 + if (!gl || !gl.lots.length) break;
284 + const payload: PagePayload = { kind: 'auction_page', auction: a, offset, lots: gl.lots };
285 + yield { url: `${url}#offset=${offset}`, externalId: `${a.auctionId}#${offset}`, kind, engine: 'api', httpStatus: 200, payload, fetchedAt: new Date() };
286 + offset += gl.lots.length;
287 + if (!gl.hasNextPage) break;
288 + }
289 + }
290 +
291 + async *crawl(ctx: CrawlContext): AsyncIterable<RawRecordInput> {
292 + const cursor = { auctions: {}, ...(ctx.options.cursor ?? {}) } as { auctions: Record<string, { state: string | null; checkedAt: string }> };
293 + const probe = ctx.options.mode === 'probe';
294 + const urls = ctx.options.seeds?.length ? ctx.options.seeds : await this.discover(ctx);
295 + // Re-check auctions previously seen open (their results become visible after close).
296 + for (const [u, s] of Object.entries(cursor.auctions)) if (s.state !== 'Closed' && !urls.includes(u)) urls.push(u);
297 + let n = 0;
298 + for (const url of urls) {
299 + if (ctx.signal?.aborted) return;
300 + const prev = cursor.auctions[url];
301 + if (prev?.state === 'Closed' && ctx.options.mode !== 'backfill') continue;
302 + if (n++ >= (probe ? 1 : this.config.maxAuctionsPerRun)) break;
303 + let state: string | null = prev?.state ?? null;
304 + for await (const raw of this.crawlAuction(ctx, url, probe)) {
305 + state = (raw.payload as PagePayload).auction.state;
306 + yield raw;
307 + }
308 + cursor.auctions[url] = { state, checkedAt: new Date().toISOString() };
309 + const entries = Object.entries(cursor.auctions);
310 + if (entries.length > 400) cursor.auctions = Object.fromEntries(entries.slice(-400));
311 + await ctx.setCursor(cursor);
312 + }
313 + }
314 +
315 + async lookup(url: string, ctx: CrawlContext): Promise<RawRecordInput[]> {
316 + const m = url.match(/^(https?:\/\/(?:www\.)?sothebys\.com\/en\/buy\/auction\/20\d{2}\/[a-z0-9-]+)(?:\/([a-z0-9-]+))?/i);
317 + if (!m) return [];
318 + const out: RawRecordInput[] = [];
319 + for await (const raw of this.crawlAuction(ctx, m[1]!, true)) {
320 + if (m[2]) {
321 + const p = raw.payload as PagePayload;
322 + p.lots = p.lots.filter((l) => l.slug === m[2]);
323 + }
324 + out.push(raw);
325 + }
326 + return out;
327 + }
328 +
329 + async normalize(raw: RawRecordLike): Promise<NormalizedRecord[]> {
330 + const page = PagePayloadSchema.parse(raw.payload);
331 + const a = page.auction;
332 + const hints = hintsForAuction(a);
333 + const out: NormalizedRecord[] = [];
334 + for (const lot of page.lots) {
335 + if (lot.withdrawn) continue;
336 + const title = lot.creators && !lot.title.toLowerCase().includes(lot.creators.toLowerCase()) ? `${lot.creators} — ${lot.title}` : lot.title;
337 + const categorySlug = classifyTitle(title, hints);
338 + if (!categorySlug) continue;
339 + const cur = currency(lot.finalCurrency ?? lot.bidCurrency ?? a.currency);
340 + if (!cur) continue;
341 + const grade = parseGradeFromTitle(title);
342 + const isWatch = ['rolex', 'patek_philippe', 'audemars_piguet', 'omega', 'other_watches'].includes(categorySlug);
343 + const reference = isWatch ? watchReference(title) : null;
344 + const identifiers: Record<string, string> = { sothebys_lot_id: lot.lotId };
345 + if (a.saleNumber) identifiers.sothebys_sale_number = a.saleNumber;
346 + if (reference) identifiers.reference = reference;
347 + if (categorySlug === 'lego_sets') {
348 + const n = legoSetNumber(title);
349 + if (n) identifiers.lego_set_number = n;
350 + }
351 + const base = {
352 + connectorId: this.meta.id,
353 + sourceId: this.meta.sourceId,
354 + sourceUrl: lotUrl(a.url, lot.slug, lot.lotId),
355 + externalId: lot.lotId,
356 + rawTitle: title,
357 + description: null,
358 + imageUrls: lot.imageUrl ? [lot.imageUrl] : [],
359 + attributes: {
360 + categorySlug,
361 + name: lot.title,
362 + brand: brandFromSlug(categorySlug, title) ?? (isWatch ? lot.creators : null),
363 + reference,
364 + year: safeYear(title),
365 + identifiers,
366 + metadata: { auction_id: a.auctionId, sale_number: a.saleNumber, auction_title: a.title, auction_type: a.type, departments: a.departments, estimate_low: lot.estimateLow, estimate_high: lot.estimateHigh, hammer_price: lot.currentBid, bids: lot.numberOfBids },
367 + },
368 + grade: { grader: grade.grader, grade: grade.grade, qualifier: grade.qualifier, certificationNumber: null },
369 + condition: {},
370 + observedAt: raw.fetchedAt,
371 + parserVersion: this.parserVersion,
372 + };
373 + const closed = a.state === 'Closed' || lot.isClosed === true;
374 + if (closed) {
375 + if (!lot.isSold || !lot.finalPrice || lot.finalPrice <= 0) continue;
376 + const saleDate = iso(lot.closingTime) ?? iso(a.closedAt) ?? iso(a.endsAt);
377 + if (!saleDate || saleDate.getTime() > Date.now() + 86_400_000) continue;
378 + out.push(
379 + NormalizedSaleSchema.parse({
380 + ...base,
381 + kind: 'sale',
382 + confidence: 0.9,
383 + saleType: 'auction',
384 + saleDate,
385 + price: lot.finalPrice,
386 + currency: cur,
387 + buyerPremiumIncluded: true,
388 + quantity: 1,
389 + isBundle: isBundleTitle(title),
390 + location: a.location,
391 + auctionHouse: "Sotheby's",
392 + lotNumber: lot.lotNumber,
393 + }),
394 + );
395 + } else {
396 + const startsAt = iso(a.startsAt);
397 + out.push(
398 + NormalizedAuctionLotSchema.parse({
399 + ...base,
400 + kind: 'auction_lot',
401 + confidence: 0.85,
402 + auctionHouse: "Sotheby's",
403 + auctionName: a.title,
404 + lotNumber: lot.lotNumber,
405 + startsAt,
406 + endsAt: iso(lot.closingTime) ?? iso(a.endsAt),
407 + estimateLow: lot.estimateLow,
408 + estimateHigh: lot.estimateHigh,
409 + currentBid: lot.currentBid,
410 + currency: cur,
411 + status: a.state === 'Opened' && startsAt && startsAt.getTime() <= Date.now() ? 'live' : 'upcoming',
412 + location: a.location,
413 + }),
414 + );
415 + }
416 + }
417 + return out;
418 + }
419 +}
added connectors/api/sothebys/meta.json +36 −0
@@ -0,0 +1,36 @@
1 +{
2 + "id": "sothebys",
3 + "displayName": "Sotheby's (auction results & upcoming lots)",
4 + "sourceId": "sothebys",
5 + "sourceName": "Sotheby's",
6 + "sourceType": "auction_house",
7 + "sourceUrl": "https://www.sothebys.com",
8 + "module": "api/sothebys",
9 + "enginePriority": ["api", "firecrawl"],
10 + "categories": ["rolex", "patek_philippe", "audemars_piguet", "omega", "other_watches", "luxury_handbags", "jewelry", "gemstones", "wine", "whisky", "cognac", "sneakers", "fashion_streetwear", "pokemon", "magic_the_gathering", "basketball_cards", "baseball_cards", "football_cards", "sports_memorabilia", "marvel_comics", "dc_comics", "independent_comics", "art", "contemporary_art", "photography", "books", "maps", "historical_documents", "coins", "banknotes", "design_furniture", "antiques", "automobiles", "space", "scientific_instruments", "fossils", "minerals", "meteorites", "music_memorabilia", "movie_memorabilia", "video_games", "vintage_toys"],
11 + "regions": ["US", "GB", "HK", "FR", "CH"],
12 + "languages": ["en"],
13 + "currency": ["USD", "GBP", "HKD", "EUR", "CHF"],
14 + "supportsListings": false,
15 + "supportsSold": true,
16 + "supportsAuctions": true,
17 + "supportsImages": true,
18 + "supportsCatalog": false,
19 + "supportsPopulation": false,
20 + "supportsLookup": true,
21 + "refreshFrequencyMinutes": 360,
22 + "priority": "high",
23 + "trustScore": 0.9,
24 + "attributionRequired": true,
25 + "termsUrl": "https://www.sothebys.com/en/terms-conditions",
26 + "accessNotes": "Auction pages https://www.sothebys.com/en/buy/auction/<year>/<slug> are server-rendered (__NEXT_DATA__ Apollo cache) with auction metadata, department names, currency, dates and the first 48 lot cards including estimates and, for closed sales, the visible result (BidState.sold.premiums.finalPriceV2 = price including buyer's premium, currentBidV2 = hammer). Remaining lots are paged with the same public GraphQL endpoint the page uses (clientapi.prod.sothelabs.com/graphql, query LotCardsFilterByPaginated, no authentication; we request only public lot-card fields). Auction discovery: links on the public /en/results and /en/calendar pages (rendered through Firecrawl, 1 credit each), plus config.seeds auction URLs; auctions seen while open are re-checked after they close so their results are captured. robots.txt disallows /bsp-api/* and PDFs — not used. Prices: finalPriceV2 (buyer's premium included) → buyerPremiumIncluded=true, hammer kept in metadata; sale date = lot closingTime or the auction's closed timestamp. Condition reports are behind login and are not fetched.",
27 + "enabled": true,
28 + "schemaVersion": "1.0",
29 + "config": {
30 + "seeds": [],
31 + "discoveryPages": ["https://www.sothebys.com/en/results", "https://www.sothebys.com/en/calendar"],
32 + "departments": [],
33 + "maxAuctionsPerRun": 25,
34 + "pageSize": 48
35 + }
36 +}
modified connectors/registry.json +528 −28
@@ -5,7 +5,7 @@
5 5 "id": "aucfree",
6 6 "displayName": "aucfree (Yahoo! Auctions Japan closed lots)",
7 7 "sourceId": "aucfree",
8 − "sourceName": "aucfree \u2014 \u30aa\u30fc\u30af\u30d5\u30ea\u30fc",
8 + "sourceName": "aucfree — オークフリー",
9 9 "sourceType": "analytics_provider",
10 10 "sourceUrl": "https://aucfree.com",
11 11 "module": "firecrawl/aucfree",
@@ -43,43 +43,43 @@
43 43 "trustScore": 0.75,
44 44 "attributionRequired": true,
45 45 "termsUrl": "https://aucfree.com/about",
46 − "accessNotes": "aucfree.com publishes closed Yahoo! Auctions Japan lots (end price, bid count, end date) free of charge; no robots.txt is served (404) so no path is disallowed. Plain HTTPS returns 403 to non-browser clients, so pages are fetched through Firecrawl (1 credit per search page of 50 lots \u2248 0.02 credit/sale) with Scrapfly as fallback. Search pages per keyword seed (`/search?o=t2&q=<kw>&p=N`, sorted by end date). Prices are JPY hammer prices without buyer premium; dates are the lot end dates (Japanese '2026\u5e749\u67086\u65e5' format). Identification is title-only (Japanese titles) \u2192 confidence 0.7; PSA/BGS grades parsed from the title. Only market data is stored; item pages, seller and bidder data are not fetched.",
46 + "accessNotes": "aucfree.com publishes closed Yahoo! Auctions Japan lots (end price, bid count, end date) free of charge; no robots.txt is served (404) so no path is disallowed. Plain HTTPS returns 403 to non-browser clients, so pages are fetched through Firecrawl (1 credit per search page of 50 lots ≈ 0.02 credit/sale) with Scrapfly as fallback. Search pages per keyword seed (`/search?o=t2&q=<kw>&p=N`, sorted by end date). Prices are JPY hammer prices without buyer premium; dates are the lot end dates (Japanese '2026年9月6日' format). Identification is title-only (Japanese titles) → confidence 0.7; PSA/BGS grades parsed from the title. Only market data is stored; item pages, seller and bidder data are not fetched.",
47 47 "enabled": true,
48 48 "schemaVersion": "1.0",
49 49 "config": {
50 50 "seeds": [
51 51 {
52 − "q": "\u30dd\u30b1\u30e2\u30f3\u30ab\u30fc\u30c9 PSA10",
52 + "q": "ポケモンカード PSA10",
53 53 "category": "pokemon",
54 54 "language": "Japanese"
55 55 },
56 56 {
57 − "q": "\u30dd\u30b1\u30e2\u30f3\u30ab\u30fc\u30c9 \u65e7\u88cf PSA",
57 + "q": "ポケモンカード 旧裏 PSA",
58 58 "category": "pokemon",
59 59 "language": "Japanese"
60 60 },
61 61 {
62 − "q": "\u904a\u622f\u738b PSA10",
62 + "q": "遊戯王 PSA10",
63 63 "category": "yugioh",
64 64 "language": "Japanese"
65 65 },
66 66 {
67 − "q": "\u30ef\u30f3\u30d4\u30fc\u30b9\u30ab\u30fc\u30c9 PSA10",
67 + "q": "ワンピースカード PSA10",
68 68 "category": "one_piece_card_game",
69 69 "language": "Japanese"
70 70 },
71 71 {
72 − "q": "\u30ac\u30f3\u30d7\u30e9 MG \u672a\u7d44\u7acb",
72 + "q": "ガンプラ MG 未組立",
73 73 "category": "gundam",
74 74 "language": null
75 75 },
76 76 {
77 − "q": "figma \u65b0\u54c1",
77 + "q": "figma 新品",
78 78 "category": "action_figures",
79 79 "language": null
80 80 },
81 81 {
82 − "q": "\u30d5\u30a1\u30df\u30b3\u30f3 \u672a\u958b\u5c01",
82 + "q": "ファミコン 未開封",
83 83 "category": "nintendo_games",
84 84 "language": null
85 85 },
@@ -92,6 +92,129 @@
92 92 "pagesPerSeed": 2
93 93 }
94 94 },
95 + {
96 + "id": "bonhams",
97 + "displayName": "Bonhams (auction results & upcoming lots)",
98 + "sourceId": "bonhams",
99 + "sourceName": "Bonhams",
100 + "sourceType": "auction_house",
101 + "sourceUrl": "https://www.bonhams.com",
102 + "module": "api/bonhams",
103 + "enginePriority": [
104 + "api"
105 + ],
106 + "categories": [
107 + "rolex",
108 + "patek_philippe",
109 + "audemars_piguet",
110 + "omega",
111 + "other_watches",
112 + "wine",
113 + "whisky",
114 + "coins",
115 + "banknotes",
116 + "medals",
117 + "automobiles",
118 + "motorcycles",
119 + "automotive_memorabilia",
120 + "luxury_handbags",
121 + "fashion_streetwear",
122 + "jewelry",
123 + "movie_memorabilia",
124 + "music_memorabilia",
125 + "musical_instruments",
126 + "movie_posters",
127 + "vintage_toys",
128 + "sports_memorabilia",
129 + "books",
130 + "maps",
131 + "photography",
132 + "art",
133 + "contemporary_art",
134 + "clocks",
135 + "silver",
136 + "glass_crystal",
137 + "porcelain",
138 + "scientific_instruments",
139 + "stamps",
140 + "fossils",
141 + "minerals",
142 + "meteorites",
143 + "militaria",
144 + "design_furniture",
145 + "antiques"
146 + ],
147 + "regions": [
148 + "GB",
149 + "US",
150 + "HK",
151 + "FR",
152 + "AU"
153 + ],
154 + "languages": [
155 + "en"
156 + ],
157 + "currency": [
158 + "GBP",
159 + "USD",
160 + "HKD",
161 + "EUR",
162 + "AUD",
163 + "CHF"
164 + ],
165 + "supportsListings": false,
166 + "supportsSold": true,
167 + "supportsAuctions": true,
168 + "supportsImages": true,
169 + "supportsCatalog": false,
170 + "supportsPopulation": false,
171 + "supportsLookup": true,
172 + "refreshFrequencyMinutes": 360,
173 + "priority": "high",
174 + "trustScore": 0.9,
175 + "attributionRequired": true,
176 + "termsUrl": "https://www.bonhams.com/legals/terms-of-use/",
177 + "accessNotes": "Plain HTTPS (no rendering, no credits). Public results listing https://www.bonhams.com/auctions/results/?page=N and upcoming listing /auctions/upcoming/ are server-rendered Next.js pages whose __NEXT_DATA__ carries 24 auctions per page (11k+ past auctions); each auction page /auction/<id>/<slug>/?page=N carries 48 lots per page with estimates, hammer price, price including buyer's premium (hammerPremium), status, currency, department and end date. bonhams.com/robots.txt only disallows /ldc/, /vms-assets/, */aggregate$ and */head_image* — none used. Prices: we store hammerPremium (hammer + buyer's premium as published by Bonhams) as the sale price with buyerPremiumIncluded=true and keep the hammer price in metadata. Sale date = the lot's hammerTime / auction end date from the source. Departments outside the configured whitelist are skipped, not guessed.",
178 + "enabled": true,
179 + "schemaVersion": "1.0",
180 + "config": {
181 + "departments": [
182 + "Watches",
183 + "Wine",
184 + "Whisky",
185 + "Coins, Medals and Banknotes",
186 + "Cars",
187 + "Motorcycles",
188 + "Automobilia",
189 + "Designer Handbags & Fashion",
190 + "Jewellery",
191 + "Popular Culture",
192 + "Sporting Memorabilia",
193 + "Books & Manuscripts",
194 + "Photographs",
195 + "Prints & Multiples",
196 + "Post-War and Contemporary Art",
197 + "Clocks",
198 + "Silver",
199 + "Glass",
200 + "Scientific Instruments",
201 + "Stamps, Covers & Postal History",
202 + "Natural History",
203 + "Arms and Armour",
204 + "Modern Decorative Art & Design",
205 + "Impressionist and Modern Art",
206 + "Modern British & Irish Art",
207 + "European Ceramics",
208 + "British Ceramics",
209 + "Travel & Exploration",
210 + "Home and Interiors"
211 + ],
212 + "maxResultsPages": 20,
213 + "maxAuctionsPerRun": 40,
214 + "upcomingAuctionsPerRun": 12,
215 + "lotsPerPage": 48
216 + }
217 + },
95 218 {
96 219 "id": "brickeconomy",
97 220 "displayName": "BrickEconomy",
@@ -129,7 +252,7 @@
129 252 "trustScore": 0.65,
130 253 "attributionRequired": true,
131 254 "termsUrl": "https://www.brickeconomy.com/legal-terms",
132 − "accessNotes": "Public set pages fetched through Firecrawl (markdown; ~1 credit/page). robots.txt allows all crawlers (explicitly including AI bots). Plain HTTPS returns 403 for non-browser agents, so Firecrawl is the primary engine and Scrapfly the fallback. We capture set facts (number, name, theme, subtheme, year, release/retire dates, pieces, minifigs), retail price, and BrickEconomy's estimated New/Sealed and Used values as guide observations \u2014 never as sales. Discovery via theme/top lists in config.seeds.",
255 + "accessNotes": "Public set pages fetched through Firecrawl (markdown; ~1 credit/page). robots.txt allows all crawlers (explicitly including AI bots). Plain HTTPS returns 403 for non-browser agents, so Firecrawl is the primary engine and Scrapfly the fallback. We capture set facts (number, name, theme, subtheme, year, release/retire dates, pieces, minifigs), retail price, and BrickEconomy's estimated New/Sealed and Used values as guide observations — never as sales. Discovery via theme/top lists in config.seeds.",
133 256 "enabled": true,
134 257 "schemaVersion": "1.0",
135 258 "config": {
@@ -184,7 +307,7 @@
184 307 "trustScore": 0.85,
185 308 "attributionRequired": true,
186 309 "termsUrl": "https://brickset.com/about",
187 − "accessNotes": "Public set pages (brickset.com/sets/<number>-1/...) and theme listings (/sets/theme-<Theme>/page-N, 25 sets per page) fetched over plain HTTPS with the RareIndex user agent; robots.txt disallows /admin, /export, /ajax, /profile, /webservices, /buy, /news, /reviews\u2026 \u2014 none of which are used (the Brickset API/webservices need a personal key: https://brickset.com/tools/webservices/requestkey). Fields parsed from the set page definition list: pieces, minifigs, RRP (GBP + USD), launch/exit dates, availability, packaging, barcodes (UPC/EAN), theme/subtheme and the 'Current value' New/Used estimates that Brickset derives from BrickLink \u2014 stored as guide_value observations (USD, confidence 0.65). 1.5 s politeness delay.",
310 + "accessNotes": "Public set pages (brickset.com/sets/<number>-1/...) and theme listings (/sets/theme-<Theme>/page-N, 25 sets per page) fetched over plain HTTPS with the RareIndex user agent; robots.txt disallows /admin, /export, /ajax, /profile, /webservices, /buy, /news, /reviews… — none of which are used (the Brickset API/webservices need a personal key: https://brickset.com/tools/webservices/requestkey). Fields parsed from the set page definition list: pieces, minifigs, RRP (GBP + USD), launch/exit dates, availability, packaging, barcodes (UPC/EAN), theme/subtheme and the 'Current value' New/Used estimates that Brickset derives from BrickLink — stored as guide_value observations (USD, confidence 0.65). 1.5 s politeness delay.",
188 311 "enabled": true,
189 312 "schemaVersion": "1.0",
190 313 "config": {
@@ -209,6 +332,284 @@
209 332 "setsPerRun": 120
210 333 }
211 334 },
335 + {
336 + "id": "catawiki",
337 + "displayName": "Catawiki (closed-lot results & live lots)",
338 + "sourceId": "catawiki",
339 + "sourceName": "Catawiki",
340 + "sourceType": "auction_house",
341 + "sourceUrl": "https://www.catawiki.com",
342 + "module": "scrapfly/catawiki",
343 + "enginePriority": [
344 + "scrapfly"
345 + ],
346 + "categories": [
347 + "pokemon",
348 + "magic_the_gathering",
349 + "yugioh",
350 + "one_piece_card_game",
351 + "disney_lorcana",
352 + "other_tcg",
353 + "basketball_cards",
354 + "baseball_cards",
355 + "football_cards",
356 + "hockey_cards",
357 + "soccer_cards",
358 + "f1_cards",
359 + "non_sport_cards",
360 + "rolex",
361 + "patek_philippe",
362 + "audemars_piguet",
363 + "omega",
364 + "other_watches",
365 + "pens",
366 + "lighters",
367 + "marvel_comics",
368 + "dc_comics",
369 + "independent_comics",
370 + "manga",
371 + "animation_art",
372 + "lego_sets",
373 + "funko",
374 + "model_cars",
375 + "model_trains",
376 + "action_figures",
377 + "vintage_toys",
378 + "designer_toys",
379 + "dolls",
380 + "plush",
381 + "video_games",
382 + "coins",
383 + "banknotes",
384 + "stamps",
385 + "medals",
386 + "wine",
387 + "whisky",
388 + "rum",
389 + "cognac",
390 + "music",
391 + "movie_posters",
392 + "cameras",
393 + "sports_memorabilia",
394 + "art",
395 + "contemporary_art",
396 + "photography",
397 + "jewelry",
398 + "gemstones",
399 + "luxury_handbags",
400 + "sneakers",
401 + "fashion_streetwear",
402 + "automobiles",
403 + "motorcycles",
404 + "automotive_memorabilia",
405 + "books",
406 + "maps",
407 + "historical_documents",
408 + "fossils",
409 + "minerals",
410 + "meteorites",
411 + "antiques",
412 + "design_furniture"
413 + ],
414 + "regions": [
415 + "NL",
416 + "EU"
417 + ],
418 + "languages": [
419 + "en"
420 + ],
421 + "currency": [
422 + "EUR"
423 + ],
424 + "supportsListings": false,
425 + "supportsSold": true,
426 + "supportsAuctions": true,
427 + "supportsImages": true,
428 + "supportsCatalog": false,
429 + "supportsPopulation": false,
430 + "supportsLookup": true,
431 + "refreshFrequencyMinutes": 240,
432 + "priority": "high",
433 + "trustScore": 0.8,
434 + "attributionRequired": true,
435 + "termsUrl": "https://www.catawiki.com/en/help/terms-of-use",
436 + "accessNotes": "Scrapfly (asp, NL exit) because catawiki.com returns 403 to non-browser clients. Two-phase crawl: (1) discovery — a rendered category page (render_js, ~6 credits) lists the live themed auctions of the category; each auction page /en/a/<id>-slug is server-rendered (__NEXT_DATA__, 1 credit, no JS) with its full lot list and closeAt; live lots are emitted as auction_lot records and remembered in the cursor; (2) harvest — after an auction closes, each remembered lot page /en/l/<id>-slug (1 credit, no JS) exposes biddingBlockResponse {closed, sold, final bid in EUR, biddingEndTime} plus title/subtitle/specifications/expert estimate/images/seller country, and sold lots become sale records. Robots (via Scrapfly): /*/c/*/* and *lot_id are disallowed — we only use single-segment category URLs, auction pages and lot pages, never the lot_id query. Prices: Catawiki's final bid is the hammer; the buyer pays an additional ~9% buyer protection fee, so buyerPremiumIncluded=false (fee noted in metadata). Sale date = biddingEndTime from the source. Unsold closed lots are discarded.",
437 + "enabled": true,
438 + "schemaVersion": "1.0",
439 + "config": {
440 + "seeds": [
441 + {
442 + "id": 725,
443 + "path": "725-trading-cards",
444 + "hint": "cards"
445 + },
446 + {
447 + "id": 299,
448 + "path": "299-watches-pens-lighters",
449 + "hint": "watches"
450 + },
451 + {
452 + "id": 139,
453 + "path": "139-comics-animation",
454 + "hint": "comics"
455 + },
456 + {
457 + "id": 363,
458 + "path": "363-toys-models",
459 + "hint": "toys"
460 + },
461 + {
462 + "id": 165,
463 + "path": "165-coins-stamps",
464 + "hint": "coins"
465 + },
466 + {
467 + "id": 720,
468 + "path": "720-wine-whisky-spirits",
469 + "hint": "wine"
470 + },
471 + {
472 + "id": 347,
473 + "path": "347-music-movies-cameras",
474 + "hint": "music"
475 + },
476 + {
477 + "id": 1097,
478 + "path": "1097-sports",
479 + "hint": "sports"
480 + },
481 + {
482 + "id": 714,
483 + "path": "714-jewellery-precious-stones",
484 + "hint": "jewelry"
485 + },
486 + {
487 + "id": 721,
488 + "path": "721-fashion",
489 + "hint": "fashion"
490 + },
491 + {
492 + "id": 85,
493 + "path": "85-art",
494 + "hint": "art"
495 + },
496 + {
497 + "id": 708,
498 + "path": "708-classic-cars-motorcycles-automobilia",
499 + "hint": "cars"
500 + },
501 + {
502 + "id": 863,
503 + "path": "863-archaeology-natural-history",
504 + "hint": "natural_history"
505 + },
506 + {
507 + "id": 1099,
508 + "path": "1099-books-historical-memorabilia",
509 + "hint": "books"
510 + }
511 + ],
512 + "maxNewAuctionsPerRun": 30,
513 + "maxLotFetchesPerRun": 400,
514 + "pendingCap": 6000,
515 + "harvestDelayMinutes": 20
516 + }
517 + },
518 + {
519 + "id": "christies",
520 + "displayName": "Christie's (auction results)",
521 + "sourceId": "christies",
522 + "sourceName": "Christie's",
523 + "sourceType": "auction_house",
524 + "sourceUrl": "https://www.christies.com",
525 + "module": "api/christies",
526 + "enginePriority": [
527 + "api"
528 + ],
529 + "categories": [
530 + "rolex",
531 + "patek_philippe",
532 + "audemars_piguet",
533 + "omega",
534 + "other_watches",
535 + "luxury_handbags",
536 + "jewelry",
537 + "gemstones",
538 + "wine",
539 + "whisky",
540 + "cognac",
541 + "art",
542 + "contemporary_art",
543 + "photography",
544 + "books",
545 + "maps",
546 + "historical_documents",
547 + "antiques",
548 + "design_furniture",
549 + "scientific_instruments",
550 + "fossils",
551 + "minerals",
552 + "meteorites",
553 + "sports_memorabilia",
554 + "movie_memorabilia",
555 + "music_memorabilia",
556 + "sneakers",
557 + "vintage_toys",
558 + "automobiles"
559 + ],
560 + "regions": [
561 + "US",
562 + "GB",
563 + "HK",
564 + "FR",
565 + "CH"
566 + ],
567 + "languages": [
568 + "en"
569 + ],
570 + "currency": [
571 + "USD",
572 + "GBP",
573 + "HKD",
574 + "EUR",
575 + "CHF"
576 + ],
577 + "supportsListings": false,
578 + "supportsSold": true,
579 + "supportsAuctions": false,
580 + "supportsImages": true,
581 + "supportsCatalog": false,
582 + "supportsPopulation": false,
583 + "supportsLookup": false,
584 + "refreshFrequencyMinutes": 720,
585 + "priority": "high",
586 + "trustScore": 0.9,
587 + "attributionRequired": true,
588 + "termsUrl": "https://www.christies.com/en/help/terms-and-conditions",
589 + "accessNotes": "Plain HTTPS JSON (no rendering, no credits) from the two endpoints the public christies.com pages themselves call: /api/discoverywebsite/auctioncalendar/auctionresults?language=en&month=M&year=Y (closed sales of a month with SaleID/SaleNumber, category/location filters and sale totals) and /api/discoverywebsite/auctionpages/lotsearch?language=en&SaleNumber=…&SaleId=…&page=N&pageSize=…&sortby=lotnumber (lots with estimate, price_realised, dates, image, lot url; max ~84 lots per page). christies.com/robots.txt (User-agent: *) disallows */search, */AjaxPages, */lotimages, */mychristies and similar — none of these paths are used. Prices realised are published by Christie's inclusive of buyer's premium → buyerPremiumIncluded=true; currency comes from price_realised_txt (e.g. 'GBP 190,500'); sale date = the lot's end_date. Categories come from the sale's category filter labels plus title keywords; unmapped lots keep the family suggested by the sale category. Upcoming lots are not exposed by these endpoints (calendar of future sales is a different client app), so supportsAuctions=false. Note: christies.com's edge drops requests whose User-Agent contains a URL or an e-mail address, so the connector identifies itself as 'RareIndex/0.1 (market data research; contact data at rareindex.io)' — no browser impersonation.",
590 + "enabled": true,
591 + "schemaVersion": "1.0",
592 + "config": {
593 + "categoryLabels": [
594 + "Jewellery, Watches & Handbags",
595 + "Wines & Spirits",
596 + "Collectibles",
597 + "Books & Manuscripts",
598 + "Science and Natural History",
599 + "Photographs & Prints",
600 + "Fine Art",
601 + "Furniture & Decorative Art",
602 + "Antiquities",
603 + "Asian Art",
604 + "Design",
605 + "Cars"
606 + ],
607 + "monthsPerRun": 2,
608 + "backfillMonths": 36,
609 + "maxSalesPerRun": 30,
610 + "pageSize": 84
611 + }
612 + },
212 613 {
213 614 "id": "chrono24",
214 615 "displayName": "Chrono24",
@@ -250,7 +651,7 @@
250 651 "trustScore": 0.7,
251 652 "attributionRequired": true,
252 653 "termsUrl": "https://www.chrono24.com/info/terms-of-use.htm",
253 − "accessNotes": "Public model listing pages (e.g. /rolex/daytona--mod2.htm) fetched through Scrapfly without JS rendering (Cloudflare shield \u2192 ~40 credits/page); robots.txt allows these paths (Crawl-delay 0.1). Each page embeds a schema.org ItemList of Offers (name, price in the site currency, image, listing URL) \u2014 we store asking prices as listings only, never as sales. No login, no per-listing detail fetch (seller details stay on Chrono24). Model pages are configured in config.seeds; pagination via --modN-P.htm.",
654 + "accessNotes": "Public model listing pages (e.g. /rolex/daytona--mod2.htm) fetched through Scrapfly without JS rendering (Cloudflare shield → ~40 credits/page); robots.txt allows these paths (Crawl-delay 0.1). Each page embeds a schema.org ItemList of Offers (name, price in the site currency, image, listing URL) — we store asking prices as listings only, never as sales. No login, no per-listing detail fetch (seller details stay on Chrono24). Model pages are configured in config.seeds; pagination via --modN-P.htm.",
254 655 "enabled": true,
255 656 "schemaVersion": "1.0",
256 657 "config": {
@@ -316,7 +717,7 @@
316 717 "trustScore": 0.9,
317 718 "attributionRequired": true,
318 719 "termsUrl": "https://www.comicconnect.com/terms",
319 − "accessNotes": "Public sold archive (/browse/comics/?filtertype=Sold, ~479k results, 20 per page) fetched over plain HTTPS with the RareIndex user agent. robots.txt: Allow / with Content-Signal search=yes, ai-train=no (we only index sale facts and link back). Each card exposes title, publisher + grade, sold date/time, 'Sold For' price and whether a 15% buyer's premium applies (bp attribute) \u2014 we store hammer price with buyer_premium_included=false and keep the premium note in metadata. No login, no bidder data. 1.5 s politeness delay.",
720 + "accessNotes": "Public sold archive (/browse/comics/?filtertype=Sold, ~479k results, 20 per page) fetched over plain HTTPS with the RareIndex user agent. robots.txt: Allow / with Content-Signal search=yes, ai-train=no (we only index sale facts and link back). Each card exposes title, publisher + grade, sold date/time, 'Sold For' price and whether a 15% buyer's premium applies (bp attribute) — we store hammer price with buyer_premium_included=false and keep the premium note in metadata. No login, no bidder data. 1.5 s politeness delay.",
320 721 "enabled": true,
321 722 "schemaVersion": "1.0",
322 723 "config": {
@@ -360,7 +761,7 @@
360 761 "trustScore": 0.85,
361 762 "attributionRequired": true,
362 763 "termsUrl": "https://support.discogs.com/hc/en-us/articles/360009334593-API-Terms-of-Use",
363 − "accessNotes": "Official public Discogs API (api.discogs.com) used unauthenticated with the RareIndex user agent: database/search (type=master), masters/{id}/versions (pressings with label, catno, country, year, format and community have/want counts) and marketplace/stats/{release_id} (lowest asking price + number for sale). Unauthenticated limit is 25 requests/minute \u2192 2.6 s throttle; price_suggestions requires a personal token and is not used. Marketplace stats have no timestamp: observationDate = fetch date (confidence 0.7). Catalog data is CC0; images are hot-linked thumbnails and attributed to Discogs. Sold-price history is not exposed publicly.",
764 + "accessNotes": "Official public Discogs API (api.discogs.com) used unauthenticated with the RareIndex user agent: database/search (type=master), masters/{id}/versions (pressings with label, catno, country, year, format and community have/want counts) and marketplace/stats/{release_id} (lowest asking price + number for sale). Unauthenticated limit is 25 requests/minute → 2.6 s throttle; price_suggestions requires a personal token and is not used. Marketplace stats have no timestamp: observationDate = fetch date (confidence 0.7). Catalog data is CC0; images are hot-linked thumbnails and attributed to Discogs. Sold-price history is not exposed publicly.",
364 765 "enabled": true,
365 766 "schemaVersion": "1.0",
366 767 "config": {
@@ -389,7 +790,7 @@
389 790 "Tyler, The Creator Igor",
390 791 "Frank Ocean Blonde",
391 792 "Arctic Monkeys AM",
392 − "Bj\u00f6rk Homogenic",
793 + "Björk Homogenic",
393 794 "Kraftwerk Autobahn",
394 795 "Sex Pistols Never Mind The Bollocks",
395 796 "Bruce Springsteen Born To Run",
@@ -451,7 +852,7 @@
451 852 "trustScore": 0.9,
452 853 "attributionRequired": true,
453 854 "termsUrl": "https://goldin.co/useragreement",
454 − "accessNotes": "Public 'Sold Items' result grids (https://goldin.co/buy/sc/<subcategory>?show_only=Sold%20Items&sort=Most_Recent_Bids&number_of_lots=240) rendered through Scrapfly (asp + JS rendering, ~6 credits per page of 240 sold lots). goldin.co/robots.txt allows /buy/ and /item/ and disallows /api/; we never call goldin.co/api ourselves \u2014 the lot data is read from the XHR (lots_v2 on their CloudFront search endpoint) that the public page performs during rendering, exactly what a browser does. Plain HTTP and Firecrawl return the empty SPA shell / an Akamai challenge. Prices: the grid shows the final price INCLUDING buyer's premium (current_price \u00d7 (1 + buyer_premium%)); we store that as the sale price with buyerPremiumIncluded=true and keep the hammer price and BP % in metadata. Sale date = lot end_timestamp; lots whose end_timestamp is in the future (placeholder private-sale dates like 2235-06-04) are skipped and counted as anomalies. Cert numbers appear only in item-page descriptions (lookup).",
855 + "accessNotes": "Public 'Sold Items' result grids (https://goldin.co/buy/sc/<subcategory>?show_only=Sold%20Items&sort=Most_Recent_Bids&number_of_lots=240) rendered through Scrapfly (asp + JS rendering, ~6 credits per page of 240 sold lots). goldin.co/robots.txt allows /buy/ and /item/ and disallows /api/; we never call goldin.co/api ourselves — the lot data is read from the XHR (lots_v2 on their CloudFront search endpoint) that the public page performs during rendering, exactly what a browser does. Plain HTTP and Firecrawl return the empty SPA shell / an Akamai challenge. Prices: the grid shows the final price INCLUDING buyer's premium (current_price × (1 + buyer_premium%)); we store that as the sale price with buyerPremiumIncluded=true and keep the hammer price and BP % in metadata. Sale date = lot end_timestamp; lots whose end_timestamp is in the future (placeholder private-sale dates like 2235-06-04) are skipped and counted as anomalies. Cert numbers appear only in item-page descriptions (lookup).",
455 856 "enabled": true,
456 857 "schemaVersion": "1.0",
457 858 "config": {
@@ -604,7 +1005,7 @@
604 1005 "trustScore": 0.7,
605 1006 "attributionRequired": true,
606 1007 "termsUrl": "https://novelship.com/terms",
607 − "accessNotes": "Public Novelship browse pages (novelship.com/sneakers/<brand>?page=N) and product pages fetched over plain HTTPS with the RareIndex user agent; robots.txt only disallows sell/auth/dashboard/pay paths. The server-rendered payload embeds each product's SKU (style code), colorway, retail cost, release date, last sale price, lowest listing price and 180-day sales count \u2014 no login or private endpoint is used. Prices are read as USD (the anonymous international storefront prices in US$; cost_retail matches US retail) with confidence 0.7; per-size asks are not exposed on listing pages. Sizes/stock are not fetched. 1.5 s politeness delay.",
1008 + "accessNotes": "Public Novelship browse pages (novelship.com/sneakers/<brand>?page=N) and product pages fetched over plain HTTPS with the RareIndex user agent; robots.txt only disallows sell/auth/dashboard/pay paths. The server-rendered payload embeds each product's SKU (style code), colorway, retail cost, release date, last sale price, lowest listing price and 180-day sales count — no login or private endpoint is used. Prices are read as USD (the anonymous international storefront prices in US$; cost_retail matches US retail) with confidence 0.7; per-size asks are not exposed on listing pages. Sizes/stock are not fetched. 1.5 s politeness delay.",
608 1009 "enabled": true,
609 1010 "schemaVersion": "1.0",
610 1011 "config": {
@@ -695,7 +1096,7 @@
695 1096 "trustScore": 0.9,
696 1097 "attributionRequired": true,
697 1098 "termsUrl": "https://www.pcgs.com/legal",
698 − "accessNotes": "Public PCGS Price Guide category pages (pcgs.com/prices/detail/<series>/<id>/most-active) \u2014 no login required; robots.txt does not restrict /prices. Plain HTTPS is refused by the CDN (403) so pages are rendered through Firecrawl (1 credit per category page \u2248 100 coins \u00d7 10 grades). Values are PCGS retail guide values in USD per grade (columns 4\u202670 and '+' grades), dated with the page's 'Last Update' stamp. Stored as guide_value observations with grader 'pcgs' and grade like MS65 / PR65 / MS65+; PCGS coin numbers are kept as identifiers (pcgs_number). Auction Prices Realized and the Population Report on pcgs.com require a Collectors account and are not fetched.",
1099 + "accessNotes": "Public PCGS Price Guide category pages (pcgs.com/prices/detail/<series>/<id>/most-active) — no login required; robots.txt does not restrict /prices. Plain HTTPS is refused by the CDN (403) so pages are rendered through Firecrawl (1 credit per category page ≈ 100 coins × 10 grades). Values are PCGS retail guide values in USD per grade (columns 4…70 and '+' grades), dated with the page's 'Last Update' stamp. Stored as guide_value observations with grader 'pcgs' and grade like MS65 / PR65 / MS65+; PCGS coin numbers are kept as identifiers (pcgs_number). Auction Prices Realized and the Population Report on pcgs.com require a Collectors account and are not fetched.",
699 1100 "enabled": true,
700 1101 "schemaVersion": "1.0",
701 1102 "config": {
@@ -770,7 +1171,7 @@
770 1171 "trustScore": 0.95,
771 1172 "attributionRequired": true,
772 1173 "termsUrl": "https://www.phillips.com/about/terms",
773 − "accessNotes": "Past watch sales are discovered from the public /auctions/past page (plain HTTPS; embedded JSON with saleNumber, title, end date, location). Each sale page is rendered through Firecrawl (JS wait ~6 s, 1 credit) to read the public lot list: lot number, maker, reference, model, estimate and 'Sold For' (Phillips publishes prices realised including buyer's premium). robots.txt disallows only /search and filter paths. No login, no bidder data. Large sales may lazy-load beyond the first ~70 lots \u2014 coverage is recorded per run.",
1174 + "accessNotes": "Past watch sales are discovered from the public /auctions/past page (plain HTTPS; embedded JSON with saleNumber, title, end date, location). Each sale page is rendered through Firecrawl (JS wait ~6 s, 1 credit) to read the public lot list: lot number, maker, reference, model, estimate and 'Sold For' (Phillips publishes prices realised including buyer's premium). robots.txt disallows only /search and filter paths. No login, no bidder data. Large sales may lazy-load beyond the first ~70 lots — coverage is recorded per run.",
774 1175 "enabled": true,
775 1176 "schemaVersion": "1.0",
776 1177 "config": {
@@ -781,9 +1182,9 @@
781 1182 },
782 1183 {
783 1184 "id": "pokemontcg",
784 − "displayName": "Pok\u00e9mon TCG API (pokemontcg.io)",
1185 + "displayName": "Pokémon TCG API (pokemontcg.io)",
785 1186 "sourceId": "pokemontcg",
786 − "sourceName": "Pok\u00e9mon TCG API",
1187 + "sourceName": "Pokémon TCG API",
787 1188 "sourceType": "catalog",
788 1189 "sourceUrl": "https://pokemontcg.io",
789 1190 "module": "api/pokemontcg",
@@ -817,7 +1218,7 @@
817 1218 "trustScore": 0.8,
818 1219 "attributionRequired": true,
819 1220 "termsUrl": "https://docs.pokemontcg.io/",
820 − "accessNotes": "Public REST API v2 (https://api.pokemontcg.io/v2). Optional X-Api-Key (POKEMONTCG_API_KEY) raises limits (20k/day) \u2014 without a key ~1k/day and 30/min. Crawl = sets, then cards per set (pageSize 250, cursor {setIndex,page}). The API is intermittently unavailable (5xx); the connector retries with backoff and falls back to the maintainers' public GitHub mirror (PokemonTCG/pokemon-tcg-data, same card schema, no prices) for the catalog when the API keeps failing. Prices are TCGplayer (USD, per printing variant: normal/holofoil/reverseHolofoil/1stEdition\u2026) and Cardmarket (EUR) daily aggregates with their own updatedAt \u2192 stored as price_observations, never as sales. Pok\u00e9mon \u00a9 Nintendo/Creatures/GAME FREAK; data attributed to pokemontcg.io.",
1221 + "accessNotes": "Public REST API v2 (https://api.pokemontcg.io/v2). Optional X-Api-Key (POKEMONTCG_API_KEY) raises limits (20k/day) — without a key ~1k/day and 30/min. Crawl = sets, then cards per set (pageSize 250, cursor {setIndex,page}). The API is intermittently unavailable (5xx); the connector retries with backoff and falls back to the maintainers' public GitHub mirror (PokemonTCG/pokemon-tcg-data, same card schema, no prices) for the catalog when the API keeps failing. Prices are TCGplayer (USD, per printing variant: normal/holofoil/reverseHolofoil/1stEdition…) and Cardmarket (EUR) daily aggregates with their own updatedAt → stored as price_observations, never as sales. Pokémon © Nintendo/Creatures/GAME FREAK; data attributed to pokemontcg.io.",
821 1222 "enabled": true,
822 1223 "schemaVersion": "1.0",
823 1224 "config": {
@@ -879,7 +1280,7 @@
879 1280 "trustScore": 0.7,
880 1281 "attributionRequired": true,
881 1282 "termsUrl": "https://www.pricecharting.com/page/terms-of-service",
882 − "accessNotes": "Public product pages fetched over plain HTTPS with the RareIndex user agent (robots.txt only disallows /buy, /publish-offer, /stripe-connect). Each product page exposes PriceCharting guide values per condition and a table of recently completed eBay sales (date, title, price, eBay item id) \u2014 we store those as sales with the PriceCharting page as source URL. No account, no API key, no photos (TimeWarp is paid and not used). Console listings paginate through the public ?format=json cursor endpoint. ~1 request per product, 1.5 s politeness delay. Trading-card consoles (Pok\u00e9mon, Magic, Yu-Gi-Oh!) are discovered from the public /category/<game>-cards pages; card pages expose guide values and eBay sales per grade (Ungraded, Grade 1\u20139.5, TAG/ACE/SGC/CGC/PSA/BGS 10, BGS 10 Black, CGC 10 Pristine). Graded rows without a named company use the generic grader 'graded' unless the eBay title names it. Pok\u00e9mon sets are mapped to pokemontcg ids/codes through the maintainers' GitHub mirror and Magic sets/cards to Scryfall (one exact-name API lookup per Magic product, \u2264 10 req/s) so sales attach to the API catalogs' canonical assets.",
1283 + "accessNotes": "Public product pages fetched over plain HTTPS with the RareIndex user agent (robots.txt only disallows /buy, /publish-offer, /stripe-connect). Each product page exposes PriceCharting guide values per condition and a table of recently completed eBay sales (date, title, price, eBay item id) — we store those as sales with the PriceCharting page as source URL. No account, no API key, no photos (TimeWarp is paid and not used). Console listings paginate through the public ?format=json cursor endpoint. ~1 request per product, 1.5 s politeness delay. Trading-card consoles (Pokémon, Magic, Yu-Gi-Oh!) are discovered from the public /category/<game>-cards pages; card pages expose guide values and eBay sales per grade (Ungraded, Grade 1–9.5, TAG/ACE/SGC/CGC/PSA/BGS 10, BGS 10 Black, CGC 10 Pristine). Graded rows without a named company use the generic grader 'graded' unless the eBay title names it. Pokémon sets are mapped to pokemontcg ids/codes through the maintainers' GitHub mirror and Magic sets/cards to Scryfall (one exact-name API lookup per Magic product, ≤ 10 req/s) so sales attach to the API catalogs' canonical assets.",
883 1284 "enabled": true,
884 1285 "schemaVersion": "2.0",
885 1286 "config": {
@@ -1010,7 +1411,7 @@
1010 1411 "trustScore": 0.85,
1011 1412 "attributionRequired": true,
1012 1413 "termsUrl": "https://scryfall.com/docs/api",
1013 − "accessNotes": "Official public API, no key. Bulk 'default_cards' JSONL (gzip, ~78 MB, refreshed daily) is streamed for the full catalog; single-card lookups use /cards/<set>/<number>. Scryfall asks for \u226410 req/s (we pace 100 ms), an identifying User-Agent and Accept headers. Prices (usd/usd_foil/usd_etched/eur/eur_foil) are Scryfall's daily market aggregates from TCGplayer/Cardmarket \u2192 stored as price_observations, never as sales. Card data \u00a9 Wizards of the Coast; Scryfall requests attribution and no implication of endorsement.",
1414 + "accessNotes": "Official public API, no key. Bulk 'default_cards' JSONL (gzip, ~78 MB, refreshed daily) is streamed for the full catalog; single-card lookups use /cards/<set>/<number>. Scryfall asks for ≤10 req/s (we pace 100 ms), an identifying User-Agent and Accept headers. Prices (usd/usd_foil/usd_etched/eur/eur_foil) are Scryfall's daily market aggregates from TCGplayer/Cardmarket → stored as price_observations, never as sales. Card data © Wizards of the Coast; Scryfall requests attribution and no implication of endorsement.",
1014 1415 "enabled": true,
1015 1416 "schemaVersion": "1.0",
1016 1417 "config": {
@@ -1018,6 +1419,105 @@
1018 1419 "requestIntervalMs": 100
1019 1420 }
1020 1421 },
1422 + {
1423 + "id": "sothebys",
1424 + "displayName": "Sotheby's (auction results & upcoming lots)",
1425 + "sourceId": "sothebys",
1426 + "sourceName": "Sotheby's",
1427 + "sourceType": "auction_house",
1428 + "sourceUrl": "https://www.sothebys.com",
1429 + "module": "api/sothebys",
1430 + "enginePriority": [
1431 + "api",
1432 + "firecrawl"
1433 + ],
1434 + "categories": [
1435 + "rolex",
1436 + "patek_philippe",
1437 + "audemars_piguet",
1438 + "omega",
1439 + "other_watches",
1440 + "luxury_handbags",
1441 + "jewelry",
1442 + "gemstones",
1443 + "wine",
1444 + "whisky",
1445 + "cognac",
1446 + "sneakers",
1447 + "fashion_streetwear",
1448 + "pokemon",
1449 + "magic_the_gathering",
1450 + "basketball_cards",
1451 + "baseball_cards",
1452 + "football_cards",
1453 + "sports_memorabilia",
1454 + "marvel_comics",
1455 + "dc_comics",
1456 + "independent_comics",
1457 + "art",
1458 + "contemporary_art",
1459 + "photography",
1460 + "books",
1461 + "maps",
1462 + "historical_documents",
1463 + "coins",
1464 + "banknotes",
1465 + "design_furniture",
1466 + "antiques",
1467 + "automobiles",
1468 + "space",
1469 + "scientific_instruments",
1470 + "fossils",
1471 + "minerals",
1472 + "meteorites",
1473 + "music_memorabilia",
1474 + "movie_memorabilia",
1475 + "video_games",
1476 + "vintage_toys"
1477 + ],
1478 + "regions": [
1479 + "US",
1480 + "GB",
1481 + "HK",
1482 + "FR",
1483 + "CH"
1484 + ],
1485 + "languages": [
1486 + "en"
1487 + ],
1488 + "currency": [
1489 + "USD",
1490 + "GBP",
1491 + "HKD",
1492 + "EUR",
1493 + "CHF"
1494 + ],
1495 + "supportsListings": false,
1496 + "supportsSold": true,
1497 + "supportsAuctions": true,
1498 + "supportsImages": true,
1499 + "supportsCatalog": false,
1500 + "supportsPopulation": false,
1501 + "supportsLookup": true,
1502 + "refreshFrequencyMinutes": 360,
1503 + "priority": "high",
1504 + "trustScore": 0.9,
1505 + "attributionRequired": true,
1506 + "termsUrl": "https://www.sothebys.com/en/terms-conditions",
1507 + "accessNotes": "Auction pages https://www.sothebys.com/en/buy/auction/<year>/<slug> are server-rendered (__NEXT_DATA__ Apollo cache) with auction metadata, department names, currency, dates and the first 48 lot cards including estimates and, for closed sales, the visible result (BidState.sold.premiums.finalPriceV2 = price including buyer's premium, currentBidV2 = hammer). Remaining lots are paged with the same public GraphQL endpoint the page uses (clientapi.prod.sothelabs.com/graphql, query LotCardsFilterByPaginated, no authentication; we request only public lot-card fields). Auction discovery: links on the public /en/results and /en/calendar pages (rendered through Firecrawl, 1 credit each), plus config.seeds auction URLs; auctions seen while open are re-checked after they close so their results are captured. robots.txt disallows /bsp-api/* and PDFs — not used. Prices: finalPriceV2 (buyer's premium included) → buyerPremiumIncluded=true, hammer kept in metadata; sale date = lot closingTime or the auction's closed timestamp. Condition reports are behind login and are not fetched.",
1508 + "enabled": true,
1509 + "schemaVersion": "1.0",
1510 + "config": {
1511 + "seeds": [],
1512 + "discoveryPages": [
1513 + "https://www.sothebys.com/en/results",
1514 + "https://www.sothebys.com/en/calendar"
1515 + ],
1516 + "departments": [],
1517 + "maxAuctionsPerRun": 25,
1518 + "pageSize": 48
1519 + }
1520 + },
1021 1521 {
1022 1522 "id": "sportscardspro",
1023 1523 "displayName": "SportsCardsPro",
@@ -1061,7 +1561,7 @@
1061 1561 "trustScore": 0.7,
1062 1562 "attributionRequired": true,
1063 1563 "termsUrl": "https://www.sportscardspro.com/page/terms-of-service",
1064 − "accessNotes": "Public product pages of PriceCharting's sports-card site. robots.txt only disallows /buy, /publish-offer, /stripe-connect. Plain HTTP with our user agent gets a Cloudflare interstitial (HTTP 403), so pages are fetched through Firecrawl (1 credit per page, ~1 MB each) \u2014 no login, no CAPTCHA solving, no account. Each page exposes guide values per grade (Ungraded, Grade 1\u20139.5, TAG/ACE/SGC/CGC/PSA/BGS 10, BGS 10 Black, CGC 10 Pristine) and recently completed eBay sales per grade tab; graded rows without a named grading company are stored with the generic grader 'graded' unless the eBay title names the company. Set lists come from the public /category/<sport>-cards pages; console listings use the ?format=json cursor endpoint.",
1564 + "accessNotes": "Public product pages of PriceCharting's sports-card site. robots.txt only disallows /buy, /publish-offer, /stripe-connect. Plain HTTP with our user agent gets a Cloudflare interstitial (HTTP 403), so pages are fetched through Firecrawl (1 credit per page, ~1 MB each) — no login, no CAPTCHA solving, no account. Each page exposes guide values per grade (Ungraded, Grade 1–9.5, TAG/ACE/SGC/CGC/PSA/BGS 10, BGS 10 Black, CGC 10 Pristine) and recently completed eBay sales per grade tab; graded rows without a named grading company are stored with the generic grader 'graded' unless the eBay title names the company. Set lists come from the public /category/<sport>-cards pages; console listings use the ?format=json cursor endpoint.",
1065 1565 "enabled": true,
1066 1566 "schemaVersion": "2.0",
1067 1567 "config": {
@@ -1100,7 +1600,7 @@
1100 1600 },
1101 1601 {
1102 1602 "id": "tcgdex",
1103 − "displayName": "TCGdex (Pok\u00e9mon, multilingual)",
1603 + "displayName": "TCGdex (Pokémon, multilingual)",
1104 1604 "sourceId": "tcgdex",
1105 1605 "sourceName": "TCGdex",
1106 1606 "sourceType": "catalog",
@@ -1142,7 +1642,7 @@
1142 1642 "trustScore": 0.8,
1143 1643 "attributionRequired": true,
1144 1644 "termsUrl": "https://tcgdex.dev/",
1145 − "accessNotes": "Open REST API (https://api.tcgdex.net/v2, no key, MIT-licensed data) covering every Pok\u00e9mon TCG language including Japanese; English cards carry TCGplayer (USD) and Cardmarket (EUR) prices per variant with their own update timestamps, which we store as price observations dated by the price's `updated` field. One request per set and per card at \u22488 req/s (self-throttled 120 ms). English ids match pokemontcg.io (base1-4) so `pokemontcg_id` aligns; set codes use the PTCGO abbreviation like pokemontcg's ptcgoCode.",
1645 + "accessNotes": "Open REST API (https://api.tcgdex.net/v2, no key, MIT-licensed data) covering every Pokémon TCG language including Japanese; English cards carry TCGplayer (USD) and Cardmarket (EUR) prices per variant with their own update timestamps, which we store as price observations dated by the price's `updated` field. One request per set and per card at ≈8 req/s (self-throttled 120 ms). English ids match pokemontcg.io (base1-4) so `pokemontcg_id` aligns; set codes use the PTCGO abbreviation like pokemontcg's ptcgoCode.",
1146 1646 "enabled": true,
1147 1647 "schemaVersion": "1.0",
1148 1648 "config": {
@@ -1189,7 +1689,7 @@
1189 1689 "trustScore": 0.75,
1190 1690 "attributionRequired": true,
1191 1691 "termsUrl": "https://ygoprodeck.com/api-guide/",
1192 − "accessNotes": "Public API v7 (https://db.ygoprodeck.com/api/v7/cardinfo.php), no key; rate limit 20 req/s \u2014 a full crawl is ONE request (~21 MB, ~14.5k cards / ~44k printings) plus optional misc=yes. The API carries no price timestamp: card_sets[].set_price (USD, per printing) and card_prices (cardmarket EUR / tcgplayer / ebay / amazon / coolstuffinc USD, card-level) are recorded as price_observations dated at fetch time with confidence 0.7 and metadata.price_scope. Images may not be hot-linked in bulk per the API guide (we store URLs, never mirror). Yu-Gi-Oh! \u00a9 Konami.",
1692 + "accessNotes": "Public API v7 (https://db.ygoprodeck.com/api/v7/cardinfo.php), no key; rate limit 20 req/s — a full crawl is ONE request (~21 MB, ~14.5k cards / ~44k printings) plus optional misc=yes. The API carries no price timestamp: card_sets[].set_price (USD, per printing) and card_prices (cardmarket EUR / tcgplayer / ebay / amazon / coolstuffinc USD, card-level) are recorded as price_observations dated at fetch time with confidence 0.7 and metadata.price_scope. Images may not be hot-linked in bulk per the API guide (we store URLs, never mirror). Yu-Gi-Oh! © Konami.",
1193 1693 "enabled": true,
1194 1694 "schemaVersion": "1.0",
1195 1695 "config": {
added connectors/scrapfly/catawiki/index.test.ts +75 −0
@@ -0,0 +1,75 @@
1 +import { describe, expect, it } from 'vitest';
2 +import { getConnectorMeta } from '@rareindex/connectors';
3 +import { loadFixture, runFixtureSuite } from '@rareindex/connectors/testing';
4 +import createConnector, { categoryPageAuctionIds, classifyLot, parseAuctionPage, parseLotPage, type AuctionLotsPayload, type LotPayload } from './index.js';
5 +
6 +const connector = createConnector(getConnectorMeta('catawiki'));
7 +
8 +describe('catawiki connector', () => {
9 + runFixtureSuite(connector, it, expect);
10 +
11 + it('turns a closed, sold lot into a hammer-price sale in EUR with the source end time', async () => {
12 + const fx = loadFixture('catawiki', 'seeded-1');
13 + const lot = fx.raw.payload as LotPayload;
14 + const out = await connector.normalize(fx.raw);
15 + expect(out).toHaveLength(1);
16 + const r = out[0]!;
17 + if (r.kind !== 'sale') throw new Error('expected sale');
18 + expect(r.price).toBe(lot.bidding.finalBidEur);
19 + expect(r.currency).toBe('EUR');
20 + expect(r.buyerPremiumIncluded).toBe(false);
21 + expect(r.saleDate.getTime()).toBe(lot.bidding.biddingEndTime);
22 + expect(r.auctionHouse).toBe('Catawiki');
23 + expect(r.location).toBe(lot.sellerCountry);
24 + expect(r.attributes.identifiers.catawiki_lot_id).toBe(String(lot.id));
25 + expect(r.attributes.metadata.estimate_min_eur).toBe(lot.estimateMinEur);
26 + expect(r.attributes.material).toBe('Wood');
27 + expect(r.attributes.categorySlug).toBe('antiques');
28 + });
29 +
30 + it('drops closed-unsold lots and emits live lots as auction_lot', async () => {
31 + const fx = loadFixture('catawiki', 'seeded-1');
32 + const lot = structuredClone(fx.raw.payload) as LotPayload;
33 + const unsold = { ...lot, bidding: { ...lot.bidding, sold: false } };
34 + expect(await connector.normalize({ ...fx.raw, payload: unsold })).toHaveLength(0);
35 + const live = { ...lot, bidding: { ...lot.bidding, closed: false, sold: null, biddingEndTime: Date.now() + 3 * 86_400_000 } };
36 + const out = await connector.normalize({ ...fx.raw, payload: live });
37 + expect(out).toHaveLength(1);
38 + expect(out[0]!.kind).toBe('auction_lot');
39 + if (out[0]!.kind === 'auction_lot') {
40 + expect(out[0]!.status).toBe('live');
41 + expect(out[0]!.currentBid).toBe(lot.bidding.finalBidEur);
42 + expect(out[0]!.estimateLow).toBe(lot.estimateMinEur);
43 + }
44 + });
45 +
46 + it('emits auction_lot records for a live themed auction and none for a stale one', async () => {
47 + const fx = loadFixture('catawiki', 'seeded-2');
48 + const payload = structuredClone(fx.raw.payload) as AuctionLotsPayload;
49 + const future = new Date(Date.now() + 2 * 86_400_000).toISOString();
50 + payload.auction = { ...payload.auction, closeAt: future, startAt: new Date(Date.now() - 86_400_000).toISOString() };
51 + const out = await connector.normalize({ ...fx.raw, payload });
52 + expect(out.length).toBeGreaterThan(payload.lots.length * 0.8);
53 + for (const r of out) {
54 + expect(r.kind).toBe('auction_lot');
55 + if (r.kind !== 'auction_lot') continue;
56 + expect(r.endsAt?.toISOString()).toBe(new Date(future).toISOString());
57 + expect(r.currency).toBe('EUR');
58 + expect(['rolex', 'patek_philippe', 'audemars_piguet', 'omega', 'other_watches', 'pens', 'lighters', 'clocks', 'jewelry']).toContain(r.attributes.categorySlug);
59 + }
60 + const stale = { ...payload, auction: { ...payload.auction, closeAt: '2020-01-01T00:00:00Z' } };
61 + expect(await connector.normalize({ ...fx.raw, payload: stale })).toHaveLength(0);
62 + });
63 +
64 + it('classifies lots from category path, specs and titles', () => {
65 + const base: LotPayload = { kind: 'lot', seedHint: 'toys', id: 1, url: 'https://www.catawiki.com/en/l/1', title: 'LEGO - Star Wars - 10179 - Millennium Falcon UCS', subtitle: 'Sealed', description: null, images: [], categoryId: null, categoryUrl: null, auction: { id: 1, title: 'LEGO Auction', url: 'https://www.catawiki.com/en/a/1', status: 'closed', startAt: null, closeAt: null, closedAt: null, categories: ['Toys & Models', 'LEGO'], lotCount: null }, specs: [{ name: 'Set number', value: '10179' }], estimateMinEur: null, estimateMaxEur: null, sellerCountry: 'NL', sellerName: null, sellerIsPro: null, bidding: { closed: true, sold: true, finalBidEur: 2500, biddingStartTime: null, biddingEndTime: 1, bidCount: null, reservePriceMet: null } };
66 + expect(classifyLot(base).slug).toBe('lego_sets');
67 + expect(classifyLot({ ...base, seedHint: 'cards', title: 'Pokémon - Charizard Base Set 4/102 - PSA 9', auction: { ...base.auction!, categories: ['Trading Cards', 'Pokémon'] } }).slug).toBe('pokemon');
68 + expect(classifyLot({ ...base, seedHint: 'watches', title: 'Rolex - Submariner 16610 - Men - 2005', auction: { ...base.auction!, categories: ['Watches, Pens & Lighters', 'Watches'] } }).slug).toBe('rolex');
69 + expect(classifyLot({ ...base, seedHint: 'wine', title: 'Macallan 18 Sherry Oak 2020 release', auction: { ...base.auction!, categories: ['Wine, Whisky & Spirits', 'Whisky'] } }).slug).toBe('whisky');
70 + expect(classifyLot({ ...base, seedHint: 'coins', title: 'Netherlands 10 Gulden 1875 gold', auction: { ...base.auction!, categories: ['Coins & Stamps', 'Coins'] } }).slug).toBe('coins');
71 + expect(categoryPageAuctionIds('<a href="/en/a/1263062-vintage"></a><a href="https://www.catawiki.com/en/a/1263062-vintage"></a><a href="/en/a/99-x">')).toEqual([1263062, 99]);
72 + expect(parseAuctionPage('<html></html>')).toBeNull();
73 + expect(parseLotPage('<html></html>', 'https://www.catawiki.com/en/l/1', 'unknown')).toBeNull();
74 + });
75 +});
added connectors/scrapfly/catawiki/index.ts +493 −0
@@ -0,0 +1,493 @@
1 +import { z } from 'zod';
2 +import { BaseConnector, type ConnectorMeta, type CrawlContext, type RawRecordInput, type RawRecordLike } from '@rareindex/connectors';
3 +import { NormalizedAuctionLotSchema, NormalizedSaleSchema, type NormalizedRecord } from '@rareindex/shared';
4 +import { normalizeCondition, parseGradeFromTitle } from '@rareindex/taxonomy';
5 +import { brandFromSlug, hintFromLabel, isBundleTitle, legoSetNumber, safeYear, slugFromTitle, watchBrand, watchReference, type DeptHint } from '../../api/_auction-lib/categories.js';
6 +
7 +/**
8 + * Catawiki — closed-lot results (hammer = final bid, EUR) and live lots, two-phase crawl.
9 + * Engine: Scrapfly. See meta.json accessNotes for the access rationale and cost model.
10 + */
11 +
12 +const SITE = 'https://www.catawiki.com';
13 +
14 +const SeedSchema = z.object({ id: z.number().int(), path: z.string(), hint: z.string() });
15 +type Seed = z.infer<typeof SeedSchema>;
16 +
17 +export const AuctionInfoSchema = z.object({
18 + id: z.number().int(),
19 + title: z.string(),
20 + url: z.string(),
21 + status: z.string().nullable(),
22 + startAt: z.string().nullable(),
23 + closeAt: z.string().nullable(),
24 + closedAt: z.string().nullable(),
25 + categories: z.array(z.string()),
26 + lotCount: z.number().nullable(),
27 +});
28 +export type AuctionInfo = z.infer<typeof AuctionInfoSchema>;
29 +
30 +export const LiveLotSchema = z.object({
31 + id: z.number().int(),
32 + title: z.string(),
33 + subtitle: z.string().nullable(),
34 + url: z.string(),
35 + imageUrl: z.string().nullable(),
36 + reservePriceSet: z.boolean().nullable(),
37 + biddingStartTime: z.string().nullable(),
38 +});
39 +export const AuctionLotsPayloadSchema = z.object({
40 + kind: z.literal('auction_lots'),
41 + seedHint: z.string(),
42 + auction: AuctionInfoSchema,
43 + lots: z.array(LiveLotSchema),
44 +});
45 +export type AuctionLotsPayload = z.infer<typeof AuctionLotsPayloadSchema>;
46 +
47 +export const LotPayloadSchema = z.object({
48 + kind: z.literal('lot'),
49 + seedHint: z.string(),
50 + id: z.number().int(),
51 + url: z.string(),
52 + title: z.string(),
53 + subtitle: z.string().nullable(),
54 + description: z.string().nullable(),
55 + images: z.array(z.string()),
56 + categoryId: z.number().nullable(),
57 + categoryUrl: z.string().nullable(),
58 + auction: AuctionInfoSchema.nullable(),
59 + specs: z.array(z.object({ name: z.string(), value: z.string() })),
60 + estimateMinEur: z.number().nullable(),
61 + estimateMaxEur: z.number().nullable(),
62 + sellerCountry: z.string().nullable(),
63 + sellerName: z.string().nullable(),
64 + sellerIsPro: z.boolean().nullable(),
65 + bidding: z.object({
66 + closed: z.boolean().nullable(),
67 + sold: z.boolean().nullable(),
68 + finalBidEur: z.number().nullable(),
69 + biddingStartTime: z.number().nullable(),
70 + biddingEndTime: z.number().nullable(),
71 + bidCount: z.number().nullable(),
72 + reservePriceMet: z.boolean().nullable(),
73 + }),
74 +});
75 +export type LotPayload = z.infer<typeof LotPayloadSchema>;
76 +
77 +const ConfigSchema = z.object({
78 + seeds: z.array(SeedSchema).default([]),
79 + maxNewAuctionsPerRun: z.number().int().default(30),
80 + maxLotFetchesPerRun: z.number().int().default(400),
81 + pendingCap: z.number().int().default(6000),
82 + harvestDelayMinutes: z.number().int().default(20),
83 +});
84 +
85 +interface Pending {
86 + id: number;
87 + url: string;
88 + auctionId: number;
89 + closeAt: string;
90 + hint: string;
91 +}
92 +interface Cursor {
93 + auctions?: Record<string, { closeAt: string | null; hint: string }>;
94 + pending?: Pending[];
95 +}
96 +
97 +export function nextData(html: string): Record<string, any> | null {
98 + const m = html.match(/<script id="__NEXT_DATA__"[^>]*>([\s\S]*?)<\/script>/);
99 + if (!m) return null;
100 + try {
101 + return (JSON.parse(m[1]!) as { props?: { pageProps?: Record<string, any> } }).props?.pageProps ?? null;
102 + } catch {
103 + return null;
104 + }
105 +}
106 +
107 +function auctionInfo(a: Record<string, any> | null | undefined): AuctionInfo | null {
108 + if (!a || !a.id) return null;
109 + return AuctionInfoSchema.parse({
110 + id: Number(a.id),
111 + title: String(a.title ?? ''),
112 + url: String(a.url ?? `${SITE}/en/a/${a.id}`),
113 + status: a.status ?? null,
114 + startAt: a.startAt ?? null,
115 + closeAt: a.closeAt ?? null,
116 + closedAt: a.closedAt ?? null,
117 + categories: ((a.categories as Array<{ title?: string; titleEn?: string }> | undefined) ?? []).map((c) => c.titleEn ?? c.title ?? '').filter(Boolean),
118 + lotCount: typeof a.lotCount === 'number' ? a.lotCount : typeof a.numberOfLots === 'number' ? a.numberOfLots : null,
119 + });
120 +}
121 +
122 +/** Auction page → auction info + live lot list. */
123 +export function parseAuctionPage(html: string): { auction: AuctionInfo; lots: z.infer<typeof LiveLotSchema>[] } | null {
124 + const pp = nextData(html);
125 + const auction = auctionInfo(pp?.auction);
126 + if (!auction) return null;
127 + const lots = ((pp?.lots as Array<Record<string, any>> | undefined) ?? []).map((l) =>
128 + LiveLotSchema.parse({
129 + id: Number(l.id),
130 + title: String(l.title ?? ''),
131 + subtitle: l.subtitle ?? null,
132 + url: String(l.url ?? `${SITE}/en/l/${l.id}`),
133 + imageUrl: l.originalImageUrl ?? l.thumbImageUrl ?? null,
134 + reservePriceSet: typeof l.reservePriceSet === 'boolean' ? l.reservePriceSet : null,
135 + biddingStartTime: l.biddingStartTime ?? null,
136 + }),
137 + );
138 + return { auction, lots };
139 +}
140 +
141 +/** Lot page → compact payload. */
142 +export function parseLotPage(html: string, url: string, seedHint: string): LotPayload | null {
143 + const pp = nextData(html);
144 + const ld = pp?.lotDetailsData;
145 + if (!ld) return null;
146 + const bb = pp?.biddingBlockResponse ?? {};
147 + const live = bb.live?.lot ?? {};
148 + const est = ld.expertsEstimate ?? {};
149 + const seller = ld.sellerInfo ?? {};
150 + const finalBid = typeof live.bid?.EUR === 'number' ? live.bid.EUR : typeof bb.localizedCurrentBidAmount === 'number' ? bb.localizedCurrentBidAmount : null;
151 + const bids = bb.biddingHistory?.bids;
152 + const bidCount = Array.isArray(bids) && bids.length ? Number(bids[0]?.totalBids ?? bids.length) : null;
153 + return LotPayloadSchema.parse({
154 + kind: 'lot',
155 + seedHint,
156 + id: Number(ld.lotId ?? pp?.lotId),
157 + url,
158 + title: String(ld.lotTitle ?? ''),
159 + subtitle: ld.lotSubtitle ?? null,
160 + description: typeof ld.description === 'string' ? ld.description.replace(/\s+/g, ' ').slice(0, 800) : null,
161 + images: ((ld.images as Array<{ large?: string; id?: string }> | undefined) ?? []).map((i) => i.large ?? i.id ?? '').filter(Boolean).slice(0, 3),
162 + categoryId: typeof ld.category?.id === 'number' ? ld.category.id : null,
163 + categoryUrl: ld.category?.url ?? null,
164 + auction: auctionInfo(pp?.auction),
165 + specs: ((ld.specifications as Array<{ name?: string; value?: string }> | undefined) ?? []).filter((s) => s.name && s.value).map((s) => ({ name: String(s.name), value: String(s.value) })),
166 + estimateMinEur: typeof est.min?.EUR === 'number' && est.min.EUR > 0 ? est.min.EUR : null,
167 + estimateMaxEur: typeof est.max?.EUR === 'number' && est.max.EUR > 0 ? est.max.EUR : null,
168 + sellerCountry: seller.address?.country?.shortCode ? String(seller.address.country.shortCode).toUpperCase() : null,
169 + sellerName: seller.sellerName ?? null,
170 + sellerIsPro: typeof seller.isPro === 'boolean' ? seller.isPro : null,
171 + bidding: {
172 + closed: typeof bb.closed === 'boolean' ? bb.closed : typeof ld.isClosed === 'boolean' ? ld.isClosed : null,
173 + sold: typeof bb.sold === 'boolean' ? bb.sold : null,
174 + finalBidEur: finalBid,
175 + biddingStartTime: typeof bb.biddingStartTime === 'number' ? bb.biddingStartTime : null,
176 + biddingEndTime: typeof bb.biddingEndTime === 'number' ? bb.biddingEndTime : typeof live.biddingEndTime === 'number' ? live.biddingEndTime : null,
177 + bidCount,
178 + reservePriceMet: typeof bb.reservePriceMet === 'boolean' ? bb.reservePriceMet : null,
179 + },
180 + });
181 +}
182 +
183 +export function categoryPageAuctionIds(html: string): number[] {
184 + return [...new Set([...html.matchAll(/\/en\/a\/(\d+)/g)].map((m) => Number(m[1])))];
185 +}
186 +
187 +function spec(specs: Array<{ name: string; value: string }>, ...names: string[]): string | null {
188 + for (const n of names) {
189 + const hit = specs.find((s) => s.name.toLowerCase() === n.toLowerCase());
190 + if (hit) return hit.value;
191 + }
192 + return null;
193 +}
194 +
195 +/** Derive taxonomy slug + attributes from a Catawiki lot (seed hint + auction categories + specs + title). */
196 +export function classifyLot(lot: LotPayload): { slug: string | null; hint: DeptHint } {
197 + const cats = lot.auction?.categories ?? [];
198 + const labelHint = hintFromLabel(cats[cats.length - 1]) !== 'unknown' ? hintFromLabel(cats[cats.length - 1]) : hintFromLabel(cats[0]);
199 + const hint: DeptHint = (lot.seedHint as DeptHint) !== 'unknown' && lot.seedHint ? (lot.seedHint as DeptHint) : labelHint;
200 + const catText = cats.join(' ');
201 + // The most specific (leaf) category decides; the full path only for franchise-style families.
202 + const leaf = cats[cats.length - 1] ?? '';
203 + const text = `${lot.title} ${lot.subtitle ?? ''}`;
204 + if (/lego/i.test(catText)) return { slug: 'lego_sets', hint };
205 + if (/funko/i.test(catText)) return { slug: 'funko', hint };
206 + if (/pok[eé]mon/i.test(catText)) return { slug: 'pokemon', hint };
207 + if (/model (?:cars|trains)|modelauto|diecast/i.test(leaf)) return { slug: /train/i.test(leaf) ? 'model_trains' : 'model_cars', hint };
208 + if (/video ?games|retro gaming/i.test(leaf)) return { slug: 'video_games', hint };
209 + if (/sneaker/i.test(leaf)) return { slug: 'sneakers', hint };
210 + if (/handbag|bags/i.test(leaf)) return { slug: 'luxury_handbags', hint };
211 + if (/whisky|whiskey/i.test(leaf)) return { slug: 'whisky', hint };
212 + if (/\bwine|champagne/i.test(leaf)) return { slug: slugFromTitle(text, 'wine') ?? 'wine', hint };
213 + if (/watch/i.test(leaf) && !/pen|lighter/i.test(leaf)) return { slug: watchBrand(text).slug, hint: 'watches' };
214 + if (/banknote/i.test(leaf)) return { slug: 'banknotes', hint };
215 + if (/stamp/i.test(leaf) && !/coin/i.test(leaf)) return { slug: 'stamps', hint };
216 + if (/coin|numismat/i.test(leaf)) return { slug: slugFromTitle(text, 'coins') ?? 'coins', hint: 'coins' };
217 + if (/vinyl|records/i.test(leaf)) return { slug: 'music', hint };
218 + if (/movie poster|film poster/i.test(leaf)) return { slug: 'movie_posters', hint };
219 + if (/camera/i.test(leaf)) return { slug: 'cameras', hint };
220 + return { slug: slugFromTitle(text, hint), hint };
221 +}
222 +
223 +function toDate(ms: number | null | undefined): Date | null {
224 + return typeof ms === 'number' && ms > 0 ? new Date(ms) : null;
225 +}
226 +
227 +export default function createConnector(meta: ConnectorMeta) {
228 + return new CatawikiConnector(meta);
229 +}
230 +
231 +export class CatawikiConnector extends BaseConnector {
232 + readonly version = '1.0.0';
233 + readonly parserVersion = '1.0.0';
234 + override readonly urlPatterns = [/^https?:\/\/(www\.)?catawiki\.[a-z]+\/[a-z]{2}\/l\/\d+/i];
235 + protected override minIntervalMs = 2000;
236 + private readonly config = ConfigSchema.parse(this.meta.config ?? {});
237 +
238 + private async html(ctx: CrawlContext, url: string, renderJs: boolean): Promise<string | null> {
239 + await this.throttle();
240 + const res = await ctx.fetch(url, { engines: ['scrapfly'], renderJs, country: 'nl', minQuality: 0, waitForMs: renderJs ? 3000 : undefined, timeoutMs: renderJs ? 120_000 : 60_000 });
241 + if (!res.success || !res.html) {
242 + ctx.anomaly('page_fetch_failed', `${url}: ${res.error ?? res.httpStatus}`);
243 + return null;
244 + }
245 + return res.html;
246 + }
247 +
248 + private async fetchLot(ctx: CrawlContext, url: string, hint: string): Promise<LotPayload | null> {
249 + const html = await this.html(ctx, url, false);
250 + if (!html) return null;
251 + const lot = parseLotPage(html, url, hint);
252 + if (!lot) ctx.anomaly('parse_failure', `${url}: no lotDetailsData`);
253 + return lot;
254 + }
255 +
256 + async *crawl(ctx: CrawlContext): AsyncIterable<RawRecordInput> {
257 + const cursor: Cursor = { auctions: {}, pending: [], ...(ctx.options.cursor ?? {}) };
258 + const probe = ctx.options.mode === 'probe';
259 + const now = Date.now();
260 + let yielded = 0;
261 +
262 + // 0. Explicit seeds (lot or auction URLs) — used by probes, smoke tests and backfills.
263 + for (const s of ctx.options.seeds ?? []) {
264 + const lotM = s.match(/\/l\/(\d+)/);
265 + if (lotM) {
266 + const lot = await this.fetchLot(ctx, s, 'unknown');
267 + if (lot && lot.bidding.closed && lot.bidding.sold) {
268 + yield { url: s, externalId: String(lot.id), kind: 'sale', engine: 'scrapfly', httpStatus: 200, payload: lot, fetchedAt: new Date() };
269 + if (this.reached(ctx, ++yielded)) return;
270 + }
271 + continue;
272 + }
273 + if (/\/a\/\d+/.test(s)) {
274 + const html = await this.html(ctx, s, false);
275 + const parsed = html ? parseAuctionPage(html) : null;
276 + if (parsed) {
277 + const payload: AuctionLotsPayload = { kind: 'auction_lots', seedHint: 'unknown', auction: parsed.auction, lots: parsed.lots };
278 + yield { url: s, externalId: `a${parsed.auction.id}`, kind: 'auction_lot', engine: 'scrapfly', httpStatus: 200, payload, fetchedAt: new Date() };
279 + this.remember(cursor, parsed, 'unknown');
280 + }
281 + }
282 + }
283 + if (probe && (ctx.options.seeds?.length ?? 0) > 0) {
284 + await ctx.setCursor(cursor as Record<string, unknown>);
285 + return;
286 + }
287 +
288 + // 1. Harvest closed lots
289 + const delayMs = this.config.harvestDelayMinutes * 60_000;
290 + const due = (cursor.pending ?? []).filter((p) => new Date(p.closeAt).getTime() + delayMs <= now).slice(0, probe ? 3 : this.config.maxLotFetchesPerRun);
291 + const dueIds = new Set(due.map((p) => p.id));
292 + for (const p of due) {
293 + if (ctx.signal?.aborted) break;
294 + const lot = await this.fetchLot(ctx, p.url, p.hint);
295 + if (lot && lot.bidding.closed === false) {
296 + // extended bidding — try again next run
297 + dueIds.delete(p.id);
298 + continue;
299 + }
300 + if (lot && lot.bidding.closed && lot.bidding.sold) {
301 + yield { url: p.url, externalId: String(lot.id), kind: 'sale', engine: 'scrapfly', httpStatus: 200, payload: lot, fetchedAt: new Date() };
302 + if (this.reached(ctx, ++yielded)) break;
303 + }
304 + }
305 + cursor.pending = (cursor.pending ?? []).filter((p) => !dueIds.has(p.id));
306 + await ctx.setCursor(cursor as Record<string, unknown>);
307 +
308 + // 2. Discovery of live auctions per seed category
309 + const seeds = ctx.options.categories?.length ? this.config.seeds.filter((s) => ctx.options.categories!.includes(s.hint)) : this.config.seeds;
310 + let newAuctions = 0;
311 + for (const seed of probe ? seeds.slice(0, 1) : seeds) {
312 + if (ctx.signal?.aborted) break;
313 + const html = await this.html(ctx, `${SITE}/en/c/${seed.path}`, true);
314 + if (!html) continue;
315 + const ids = categoryPageAuctionIds(html);
316 + if (!ids.length) ctx.anomaly('empty_page', `category ${seed.path}: no auction links after render`);
317 + for (const id of ids) {
318 + if (cursor.auctions?.[String(id)]) continue;
319 + if (newAuctions >= (probe ? 1 : this.config.maxNewAuctionsPerRun)) break;
320 + const url = `${SITE}/en/a/${id}`;
321 + const ahtml = await this.html(ctx, url, false);
322 + const parsed = ahtml ? parseAuctionPage(ahtml) : null;
323 + if (!parsed) continue;
324 + newAuctions++;
325 + this.remember(cursor, parsed, seed.hint);
326 + if (parsed.lots.length) {
327 + const payload: AuctionLotsPayload = { kind: 'auction_lots', seedHint: seed.hint, auction: parsed.auction, lots: parsed.lots };
328 + yield { url: parsed.auction.url, externalId: `a${parsed.auction.id}`, kind: 'auction_lot', engine: 'scrapfly', httpStatus: 200, payload, fetchedAt: new Date() };
329 + }
330 + await ctx.setCursor(cursor as Record<string, unknown>);
331 + }
332 + }
333 + // prune remembered auctions older than 30 days
334 + const cutoff = now - 30 * 86_400_000;
335 + for (const [id, a] of Object.entries(cursor.auctions ?? {})) if (a.closeAt && new Date(a.closeAt).getTime() < cutoff) delete cursor.auctions![id];
336 + await ctx.setCursor(cursor as Record<string, unknown>);
337 + }
338 +
339 + private remember(cursor: Cursor, parsed: NonNullable<ReturnType<typeof parseAuctionPage>>, hint: string): void {
340 + cursor.auctions ??= {};
341 + cursor.pending ??= [];
342 + cursor.auctions[String(parsed.auction.id)] = { closeAt: parsed.auction.closeAt, hint };
343 + if (!parsed.auction.closeAt) return;
344 + const known = new Set(cursor.pending.map((p) => p.id));
345 + for (const l of parsed.lots) {
346 + if (known.has(l.id)) continue;
347 + cursor.pending.push({ id: l.id, url: l.url, auctionId: parsed.auction.id, closeAt: parsed.auction.closeAt, hint });
348 + }
349 + if (cursor.pending.length > this.config.pendingCap) cursor.pending = cursor.pending.slice(-this.config.pendingCap);
350 + }
351 +
352 + async lookup(url: string, ctx: CrawlContext): Promise<RawRecordInput[]> {
353 + const lot = await this.fetchLot(ctx, url, 'unknown');
354 + if (!lot) return [];
355 + return [{ url, externalId: String(lot.id), kind: lot.bidding.closed ? 'sale' : 'auction_lot', engine: 'scrapfly', httpStatus: 200, payload: lot, fetchedAt: new Date() }];
356 + }
357 +
358 + async normalize(raw: RawRecordLike): Promise<NormalizedRecord[]> {
359 + const p = raw.payload as { kind?: string };
360 + if (p?.kind === 'auction_lots') return this.normalizeAuctionLots(raw, AuctionLotsPayloadSchema.parse(raw.payload));
361 + const lot = LotPayloadSchema.parse(raw.payload);
362 + const { slug } = classifyLot(lot);
363 + if (!slug) return [];
364 + const text = `${lot.title} ${lot.subtitle ?? ''}`.trim();
365 + const grade = parseGradeFromTitle(text);
366 + const grader = spec(lot.specs, 'Grading company', 'Graded by');
367 + const gradeSpec = spec(lot.specs, 'Grade', 'Card grade');
368 + const brandSpec = spec(lot.specs, 'Brand', 'Manufacturer', 'Producer', 'Publisher', 'Winery', 'Distillery');
369 + const model = spec(lot.specs, 'Model', 'Series', 'Theme', 'Set');
370 + const reference = spec(lot.specs, 'Reference number', 'Reference', 'Set number', 'Catalogue number') ?? (['rolex', 'patek_philippe', 'audemars_piguet', 'omega', 'other_watches'].includes(slug) ? watchReference(text) : null);
371 + const yearSpec = spec(lot.specs, 'Year', 'Year of production', 'Vintage', 'Year of publication', 'Release year');
372 + const conditionRaw = spec(lot.specs, 'Condition', 'Card condition', 'Condition of the item');
373 + const identifiers: Record<string, string> = { catawiki_lot_id: String(lot.id) };
374 + if (reference) identifiers.reference = reference;
375 + if (slug === 'lego_sets') {
376 + const n = spec(lot.specs, 'Set number') ?? legoSetNumber(text);
377 + if (n) identifiers.lego_set_number = n;
378 + }
379 + const attributes = {
380 + categorySlug: slug,
381 + name: lot.title,
382 + brand: brandSpec ?? brandFromSlug(slug, text),
383 + model,
384 + reference,
385 + year: yearSpec ? safeYear(yearSpec) : safeYear(text),
386 + country: spec(lot.specs, 'Country of origin', 'Country'),
387 + material: spec(lot.specs, 'Material'),
388 + identifiers,
389 + metadata: { auction_id: lot.auction?.id ?? null, auction_title: lot.auction?.title ?? null, auction_categories: lot.auction?.categories ?? [], category_id: lot.categoryId, category_url: lot.categoryUrl, specs: Object.fromEntries(lot.specs.map((s) => [s.name, s.value])), estimate_min_eur: lot.estimateMinEur, estimate_max_eur: lot.estimateMaxEur, seller_country: lot.sellerCountry, seller_pro: lot.sellerIsPro, bids: lot.bidding.bidCount, buyer_fee_note: 'Catawiki charges the buyer an additional protection fee (~9% + VAT) on top of the final bid' },
390 + };
391 + const base = {
392 + connectorId: this.meta.id,
393 + sourceId: this.meta.sourceId,
394 + sourceUrl: lot.url,
395 + externalId: String(lot.id),
396 + rawTitle: text,
397 + description: lot.description,
398 + imageUrls: lot.images,
399 + attributes,
400 + grade: { grader: grader ? (parseGradeFromTitle(`${grader} 1`).grader ?? grader.toLowerCase()) : grade.grader, grade: gradeSpec ?? grade.grade, qualifier: grade.qualifier, certificationNumber: spec(lot.specs, 'Certificate number', 'Certification number') },
401 + condition: { condition: normalizeCondition(slug, conditionRaw), conditionRaw, completeness: null },
402 + observedAt: raw.fetchedAt,
403 + parserVersion: this.parserVersion,
404 + };
405 + const endsAt = toDate(lot.bidding.biddingEndTime);
406 + if (lot.bidding.closed && lot.bidding.sold && lot.bidding.finalBidEur && endsAt) {
407 + if (endsAt.getTime() > Date.now() + 86_400_000) return [];
408 + return [
409 + NormalizedSaleSchema.parse({
410 + ...base,
411 + kind: 'sale',
412 + confidence: 0.85,
413 + saleType: 'auction',
414 + saleDate: endsAt,
415 + price: lot.bidding.finalBidEur,
416 + currency: 'EUR',
417 + buyerPremiumIncluded: false,
418 + quantity: 1,
419 + isBundle: isBundleTitle(text),
420 + location: lot.sellerCountry,
421 + auctionHouse: 'Catawiki',
422 + lotNumber: null,
423 + }),
424 + ];
425 + }
426 + if (!lot.bidding.closed) {
427 + return [
428 + NormalizedAuctionLotSchema.parse({
429 + ...base,
430 + kind: 'auction_lot',
431 + confidence: 0.8,
432 + auctionHouse: 'Catawiki',
433 + auctionName: lot.auction?.title ?? null,
434 + lotNumber: null,
435 + startsAt: toDate(lot.bidding.biddingStartTime),
436 + endsAt,
437 + estimateLow: lot.estimateMinEur,
438 + estimateHigh: lot.estimateMaxEur,
439 + currentBid: lot.bidding.finalBidEur,
440 + currency: 'EUR',
441 + status: 'live',
442 + location: lot.sellerCountry,
443 + }),
444 + ];
445 + }
446 + return [];
447 + }
448 +
449 + private normalizeAuctionLots(raw: RawRecordLike, page: AuctionLotsPayload): NormalizedRecord[] {
450 + const out: NormalizedRecord[] = [];
451 + const a = page.auction;
452 + const closeAt = a.closeAt ? new Date(a.closeAt) : null;
453 + const startAt = a.startAt ? new Date(a.startAt) : null;
454 + if (closeAt && closeAt.getTime() < Date.now()) return []; // stale listing page
455 + const catLabel = a.categories[a.categories.length - 1] ?? a.categories[0] ?? null;
456 + for (const l of page.lots) {
457 + const text = `${l.title} ${l.subtitle ?? ''}`.trim();
458 + const slug = classifyLot({ kind: 'lot', seedHint: page.seedHint, id: l.id, url: l.url, title: l.title, subtitle: l.subtitle, description: null, images: [], categoryId: null, categoryUrl: null, auction: a, specs: [], estimateMinEur: null, estimateMaxEur: null, sellerCountry: null, sellerName: null, sellerIsPro: null, bidding: { closed: false, sold: null, finalBidEur: null, biddingStartTime: null, biddingEndTime: null, bidCount: null, reservePriceMet: null } }).slug;
459 + if (!slug) continue;
460 + const grade = parseGradeFromTitle(text);
461 + out.push(
462 + NormalizedAuctionLotSchema.parse({
463 + kind: 'auction_lot',
464 + connectorId: this.meta.id,
465 + sourceId: this.meta.sourceId,
466 + sourceUrl: l.url,
467 + externalId: String(l.id),
468 + rawTitle: text,
469 + description: null,
470 + imageUrls: l.imageUrl ? [l.imageUrl] : [],
471 + attributes: { categorySlug: slug, name: l.title, brand: brandFromSlug(slug, text), year: safeYear(text), identifiers: { catawiki_lot_id: String(l.id) }, metadata: { auction_id: a.id, auction_title: a.title, auction_categories: a.categories, category_label: catLabel } },
472 + grade: { grader: grade.grader, grade: grade.grade, qualifier: grade.qualifier, certificationNumber: null },
473 + condition: {},
474 + observedAt: raw.fetchedAt,
475 + confidence: 0.7,
476 + parserVersion: this.parserVersion,
477 + auctionHouse: 'Catawiki',
478 + auctionName: a.title,
479 + lotNumber: null,
480 + startsAt: startAt,
481 + endsAt: closeAt,
482 + estimateLow: null,
483 + estimateHigh: null,
484 + currentBid: null,
485 + currency: 'EUR',
486 + status: startAt && startAt.getTime() <= Date.now() ? 'live' : 'upcoming',
487 + location: null,
488 + }),
489 + );
490 + }
491 + return out;
492 + }
493 +}
added connectors/scrapfly/catawiki/meta.json +51 −0
@@ -0,0 +1,51 @@
1 +{
2 + "id": "catawiki",
3 + "displayName": "Catawiki (closed-lot results & live lots)",
4 + "sourceId": "catawiki",
5 + "sourceName": "Catawiki",
6 + "sourceType": "auction_house",
7 + "sourceUrl": "https://www.catawiki.com",
8 + "module": "scrapfly/catawiki",
9 + "enginePriority": ["scrapfly"],
10 + "categories": ["pokemon", "magic_the_gathering", "yugioh", "one_piece_card_game", "disney_lorcana", "other_tcg", "basketball_cards", "baseball_cards", "football_cards", "hockey_cards", "soccer_cards", "f1_cards", "non_sport_cards", "rolex", "patek_philippe", "audemars_piguet", "omega", "other_watches", "pens", "lighters", "marvel_comics", "dc_comics", "independent_comics", "manga", "animation_art", "lego_sets", "funko", "model_cars", "model_trains", "action_figures", "vintage_toys", "designer_toys", "dolls", "plush", "video_games", "coins", "banknotes", "stamps", "medals", "wine", "whisky", "rum", "cognac", "music", "movie_posters", "cameras", "sports_memorabilia", "art", "contemporary_art", "photography", "jewelry", "gemstones", "luxury_handbags", "sneakers", "fashion_streetwear", "automobiles", "motorcycles", "automotive_memorabilia", "books", "maps", "historical_documents", "fossils", "minerals", "meteorites", "antiques", "design_furniture"],
11 + "regions": ["NL", "EU"],
12 + "languages": ["en"],
13 + "currency": ["EUR"],
14 + "supportsListings": false,
15 + "supportsSold": true,
16 + "supportsAuctions": true,
17 + "supportsImages": true,
18 + "supportsCatalog": false,
19 + "supportsPopulation": false,
20 + "supportsLookup": true,
21 + "refreshFrequencyMinutes": 240,
22 + "priority": "high",
23 + "trustScore": 0.8,
24 + "attributionRequired": true,
25 + "termsUrl": "https://www.catawiki.com/en/help/terms-of-use",
26 + "accessNotes": "Scrapfly (asp, NL exit) because catawiki.com returns 403 to non-browser clients. Two-phase crawl: (1) discovery — a rendered category page (render_js, ~6 credits) lists the live themed auctions of the category; each auction page /en/a/<id>-slug is server-rendered (__NEXT_DATA__, 1 credit, no JS) with its full lot list and closeAt; live lots are emitted as auction_lot records and remembered in the cursor; (2) harvest — after an auction closes, each remembered lot page /en/l/<id>-slug (1 credit, no JS) exposes biddingBlockResponse {closed, sold, final bid in EUR, biddingEndTime} plus title/subtitle/specifications/expert estimate/images/seller country, and sold lots become sale records. Robots (via Scrapfly): /*/c/*/* and *lot_id are disallowed — we only use single-segment category URLs, auction pages and lot pages, never the lot_id query. Prices: Catawiki's final bid is the hammer; the buyer pays an additional ~9% buyer protection fee, so buyerPremiumIncluded=false (fee noted in metadata). Sale date = biddingEndTime from the source. Unsold closed lots are discarded.",
27 + "enabled": true,
28 + "schemaVersion": "1.0",
29 + "config": {
30 + "seeds": [
31 + { "id": 725, "path": "725-trading-cards", "hint": "cards" },
32 + { "id": 299, "path": "299-watches-pens-lighters", "hint": "watches" },
33 + { "id": 139, "path": "139-comics-animation", "hint": "comics" },
34 + { "id": 363, "path": "363-toys-models", "hint": "toys" },
35 + { "id": 165, "path": "165-coins-stamps", "hint": "coins" },
36 + { "id": 720, "path": "720-wine-whisky-spirits", "hint": "wine" },
37 + { "id": 347, "path": "347-music-movies-cameras", "hint": "music" },
38 + { "id": 1097, "path": "1097-sports", "hint": "sports" },
39 + { "id": 714, "path": "714-jewellery-precious-stones", "hint": "jewelry" },
40 + { "id": 721, "path": "721-fashion", "hint": "fashion" },
41 + { "id": 85, "path": "85-art", "hint": "art" },
42 + { "id": 708, "path": "708-classic-cars-motorcycles-automobilia", "hint": "cars" },
43 + { "id": 863, "path": "863-archaeology-natural-history", "hint": "natural_history" },
44 + { "id": 1099, "path": "1099-books-historical-memorabilia", "hint": "books" }
45 + ],
46 + "maxNewAuctionsPerRun": 30,
47 + "maxLotFetchesPerRun": 400,
48 + "pendingCap": 6000,
49 + "harvestDelayMinutes": 20
50 + }
51 +}
added data/fixtures/bonhams/results-1.json +1106 −0
@@ -0,0 +1,1106 @@
1 +{
2 + "raw": {
3 + "url": "https://www.bonhams.com/auction/32080/hong-kong-online-watches-beyond-time/",
4 + "externalId": "32080#1",
5 + "kind": "sale",
6 + "engine": "api",
7 + "httpStatus": 200,
8 + "payload": {
9 + "kind": "auction_lots",
10 + "auction": {
11 + "id": "32080",
12 + "title": "Hong Kong Online Watches: Beyond Time",
13 + "slug": "hong-kong-online-watches-beyond-time",
14 + "status": "READY",
15 + "type": "ONLINE",
16 + "departments": [
17 + "Watches"
18 + ],
19 + "categories": [
20 + "Handbags, Jewels & Watches"
21 + ],
22 + "currency": "HKD",
23 + "country": "HK",
24 + "venue": "Online, Hong Kong",
25 + "start": "2026-08-26T04:00:00+00:00",
26 + "end": "2026-09-03T08:00:00+00:00",
27 + "isEnded": false,
28 + "numberOfLots": 84
29 + },
30 + "page": 1,
31 + "nbHits": 84,
32 + "lots": [
33 + {
34 + "lotId": "1001",
35 + "lotUniqueId": "6184003",
36 + "lotNo": "1001",
37 + "title": "ŌTSUKA LŌTEC | NO.5 KAI, A BRAND NEW STAINLESS STEEL SEMI-SKELETONISED WRISTWATCH WITH WANDERING HOURS, CIRCA 2026",
38 + "heading": null,
39 + "slug": "otsuka-lotec-no5-kai-a-brand-new-stainless-steel-semi-skeletonised-wristwatch-with-wandering-hours-circa-2026",
40 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25890386-1-5.jpg",
41 + "estimateLow": 40000,
42 + "estimateHigh": 80000,
43 + "hammerPrice": 85000,
44 + "hammerPremium": 108800,
45 + "startingBid": 36000,
46 + "currency": "HKD",
47 + "status": "SOLD",
48 + "hammerTime": "2026-09-03T08:00:00+00:00",
49 + "endDate": "2026-09-03T08:00:00+00:00",
50 + "department": "Watches",
51 + "categories": [],
52 + "isEnded": false,
53 + "isWithoutReserve": false
54 + },
55 + {
56 + "lotId": "1002",
57 + "lotUniqueId": "6184004",
58 + "lotNo": "1002",
59 + "title": "[NO RESERVE] ŌTSUKA LŌTEC | NO.7.5, A RARE BRAND NEW STAINLESS STEEL WRISTWATCH WITH JUMPING HOURS, CIRCA 2026",
60 + "heading": null,
61 + "slug": "no-reserve-otsuka-lotec-no75-a-rare-brand-new-stainless-steel-wristwatch-with-jumping-hours-circa-2026",
62 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25890386-2-5.jpg",
63 + "estimateLow": 20000,
64 + "estimateHigh": 40000,
65 + "hammerPrice": 65000,
66 + "hammerPremium": 83200,
67 + "startingBid": 10000,
68 + "currency": "HKD",
69 + "status": "SOLD",
70 + "hammerTime": "2026-09-03T08:01:00+00:00",
71 + "endDate": "2026-09-03T08:00:00+00:00",
72 + "department": "Watches",
73 + "categories": [],
74 + "isEnded": false,
75 + "isWithoutReserve": true
76 + },
77 + {
78 + "lotId": "1003",
79 + "lotUniqueId": "6184005",
80 + "lotNo": "1003",
81 + "title": "[NO RESERVE] ŌTSUKA LŌTEC | NO.6, A BRAND NEW STAINLESS STEEL WRISTWATCH WITH RETROGRADE HOURS AND MINUTES, CIRCA 2026",
82 + "heading": null,
83 + "slug": "no-reserve-otsuka-lotec-no6-a-brand-new-stainless-steel-wristwatch-with-retrograde-hours-and-minutes-circa-2026",
84 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25878926-1-5.jpg",
85 + "estimateLow": 20000,
86 + "estimateHigh": 40000,
87 + "hammerPrice": 65000,
88 + "hammerPremium": 83200,
89 + "startingBid": 10000,
90 + "currency": "HKD",
91 + "status": "SOLD",
92 + "hammerTime": "2026-09-03T08:02:00+00:00",
93 + "endDate": "2026-09-03T08:00:00+00:00",
94 + "department": "Watches",
95 + "categories": [],
96 + "isEnded": false,
97 + "isWithoutReserve": true
98 + },
99 + {
100 + "lotId": "1004",
101 + "lotUniqueId": "6184006",
102 + "lotNo": "1004",
103 + "title": "PARMIGIANI FLEURIER | TONDA, REF.PFC914-1020001-100182, A BRAND NEW STAINLESS STEEL BRACELET WATCH WITH DATE, CIRCA 2026",
104 + "heading": null,
105 + "slug": "parmigiani-fleurier-tonda-refpfc914-1020001-100182-a-brand-new-stainless-steel-bracelet-watch-with-date-circa-2026",
106 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25901935-11-1.jpg",
107 + "estimateLow": 70000,
108 + "estimateHigh": 140000,
109 + "hammerPrice": 100000,
110 + "hammerPremium": 128000,
111 + "startingBid": 60000,
112 + "currency": "HKD",
113 + "status": "SOLD",
114 + "hammerTime": "2026-09-03T08:03:00+00:00",
115 + "endDate": "2026-09-03T08:00:00+00:00",
116 + "department": "Watches",
117 + "categories": [],
118 + "isEnded": false,
119 + "isWithoutReserve": false
120 + },
121 + {
122 + "lotId": "1005",
123 + "lotUniqueId": "6184007",
124 + "lotNo": "1005",
125 + "title": "URWERK | REF.UR-100V T-REX, AN INNOVATIVE AND WELL-PRESERVED LIMITED EDITION BRONZED AND PVD TITANIUM SEMI-SKELETONISED WRISTWATCH WITH REVOLVING SATELLITE HOURS, DISTANCE TRAVELLED ON EARTH AND DISTANCE TRAVELLED BY EARTH INDICATION, CIRCA 2021",
126 + "heading": null,
127 + "slug": "urwerk-refur-100v-t-rex-an-innovative-and-well-preserved-limited-edition-bronzed-and-pvd-titanium-semi-skeletonised-wristwatch-with-revolving-satellite-hours-distance-travelled-on-earth-and-distance-travelled-by-earth-indication-circa-2021",
128 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/26/25901935-6-5.jpg",
129 + "estimateLow": 220000,
130 + "estimateHigh": 440000,
131 + "hammerPrice": 200000,
132 + "hammerPremium": 256000,
133 + "startingBid": 170000,
134 + "currency": "HKD",
135 + "status": "SOLD",
136 + "hammerTime": "2026-09-03T08:04:00+00:00",
137 + "endDate": "2026-09-03T08:00:00+00:00",
138 + "department": "Watches",
139 + "categories": [],
140 + "isEnded": false,
141 + "isWithoutReserve": false
142 + },
143 + {
144 + "lotId": "1006",
145 + "lotUniqueId": "6184008",
146 + "lotNo": "1006",
147 + "title": "TUDOR | HERITAGE BLACK BAY BRONZE BLUE BUCHERER EDITION, REF.79250B, A SPECIAL EDITION BRONZE WRISTWATCH MADE TO CELEBRATE THE 130TH ANNIVERSARY OF BUCHERER, CIRCA 2018",
148 + "heading": null,
149 + "slug": "tudor-heritage-black-bay-bronze-blue-bucherer-edition-ref79250b-a-special-edition-bronze-wristwatch-made-to-celebrate-the-130th-anniversary-of-bucherer-circa-2018",
150 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25907584-2-1.jpg",
151 + "estimateLow": 10000,
152 + "estimateHigh": 20000,
153 + "hammerPrice": 17000,
154 + "hammerPremium": 21760,
155 + "startingBid": 8500,
156 + "currency": "HKD",
157 + "status": "SOLD",
158 + "hammerTime": "2026-09-03T08:05:00+00:00",
159 + "endDate": "2026-09-03T08:00:00+00:00",
160 + "department": "Watches",
161 + "categories": [],
162 + "isEnded": false,
163 + "isWithoutReserve": false
164 + },
165 + {
166 + "lotId": "1007",
167 + "lotUniqueId": "6184009",
168 + "lotNo": "1007",
169 + "title": "OMEGA | SPEEDMASTER MOONPHASE \"BLUE SIDE OF THE MOON\", REF.304.93.44.52.03.002, A LIKE NEW CERAMIC CHRONOGRAPH WRISTWATCH WITH MOON PHASES, DATE AND AVENTURINE DIAL, CIRCA 2025",
170 + "heading": null,
171 + "slug": "omega-speedmaster-moonphase-blue-side-of-the-moon-ref30493445203002-a-like-new-ceramic-chronograph-wristwatch-with-moon-phases-date-and-aventurine-dial-circa-2025",
172 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/25/25907584-7-4.jpg",
173 + "estimateLow": 40000,
174 + "estimateHigh": 80000,
175 + "hammerPrice": 60000,
176 + "hammerPremium": 76800,
177 + "startingBid": 32000,
178 + "currency": "HKD",
179 + "status": "SOLD",
180 + "hammerTime": "2026-09-03T08:06:00+00:00",
181 + "endDate": "2026-09-03T08:00:00+00:00",
182 + "department": "Watches",
183 + "categories": [],
184 + "isEnded": false,
185 + "isWithoutReserve": false
186 + },
187 + {
188 + "lotId": "1008",
189 + "lotUniqueId": "6184010",
190 + "lotNo": "1008",
191 + "title": "OMEGA | SPEEDMASTER \"PROFESSIONAL\", REF.105.012-66, A STAINLESS STEEL CHRONOGRAPH WRISTWATCH WITH CB CASE, CIRCA 1967",
192 + "heading": null,
193 + "slug": "omega-speedmaster-professional-ref105012-66-a-stainless-steel-chronograph-wristwatch-with-cb-case-circa-1967",
194 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25902351-1-3.jpg",
195 + "estimateLow": 28000,
196 + "estimateHigh": 56000,
197 + "hammerPrice": 30000,
198 + "hammerPremium": 38400,
199 + "startingBid": 24000,
200 + "currency": "HKD",
201 + "status": "SOLD",
202 + "hammerTime": "2026-09-03T08:07:00+00:00",
203 + "endDate": "2026-09-03T08:00:00+00:00",
204 + "department": "Watches",
205 + "categories": [],
206 + "isEnded": false,
207 + "isWithoutReserve": false
208 + },
209 + {
210 + "lotId": "1009",
211 + "lotUniqueId": "6184011",
212 + "lotNo": "1009",
213 + "title": "[NO RESERVE] OMEGA | SPEEDMASTER CHRONOSCOPE, REF.329.30.43.51.03.001, A BRAND NEW STAINLESS STEEL CHRONOGRAPH BRACELET WATCH, CIRCA 2026",
214 + "heading": null,
215 + "slug": "no-reserve-omega-speedmaster-chronoscope-ref32930435103001-a-brand-new-stainless-steel-chronograph-bracelet-watch-circa-2026",
216 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25901935-3-1.jpg",
217 + "estimateLow": 20000,
218 + "estimateHigh": 40000,
219 + "hammerPrice": 36000,
220 + "hammerPremium": 46080,
221 + "startingBid": 10000,
222 + "currency": "HKD",
223 + "status": "SOLD",
224 + "hammerTime": "2026-09-03T08:08:00+00:00",
225 + "endDate": "2026-09-03T08:00:00+00:00",
226 + "department": "Watches",
227 + "categories": [],
228 + "isEnded": false,
229 + "isWithoutReserve": true
230 + },
231 + {
232 + "lotId": "1010",
233 + "lotUniqueId": "6178242",
234 + "lotNo": "1010",
235 + "title": "ROLEX | GMT-MASTER II, REF.126719BLRO, A WHITE GOLD DUAL TIME BRACELET WATCH WITH METEORITE DIAL, CERAMIC BEZEL AND DATE, CIRCA 2019",
236 + "heading": null,
237 + "slug": "rolex-gmt-master-ii-ref126719blro-a-white-gold-dual-time-bracelet-watch-with-meteorite-dial-ceramic-bezel-and-date-circa-2019",
238 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25880933-1-4.jpg",
239 + "estimateLow": 300000,
240 + "estimateHigh": 600000,
241 + "hammerPrice": 360000,
242 + "hammerPremium": 460800,
243 + "startingBid": 260000,
244 + "currency": "HKD",
245 + "status": "SOLD",
246 + "hammerTime": "2026-09-03T08:09:00+00:00",
247 + "endDate": "2026-09-03T08:00:00+00:00",
248 + "department": "Watches",
249 + "categories": [],
250 + "isEnded": false,
251 + "isWithoutReserve": false
252 + },
253 + {
254 + "lotId": "1011",
255 + "lotUniqueId": "6184012",
256 + "lotNo": "1011",
257 + "title": "ROLEX | COSMOGRAPH DAYTONA, REF.116519LN, A WHITE GOLD CHRONOGRAPH BRACELET WATCH WITH CERAMIC BEZEL, CIRCA 2017",
258 + "heading": null,
259 + "slug": "rolex-cosmograph-daytona-ref116519ln-a-white-gold-chronograph-bracelet-watch-with-ceramic-bezel-circa-2017",
260 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25898045-1-1.jpg",
261 + "estimateLow": 200000,
262 + "estimateHigh": 400000,
263 + "hammerPrice": 300000,
264 + "hammerPremium": 384000,
265 + "startingBid": 180000,
266 + "currency": "HKD",
267 + "status": "SOLD",
268 + "hammerTime": "2026-09-03T08:10:00+00:00",
269 + "endDate": "2026-09-03T08:00:00+00:00",
270 + "department": "Watches",
271 + "categories": [],
272 + "isEnded": false,
273 + "isWithoutReserve": false
274 + },
275 + {
276 + "lotId": "1012",
277 + "lotUniqueId": "6184013",
278 + "lotNo": "1012",
279 + "title": "ROLEX | DAY-DATE, REF.1803, A WHITE GOLD BRACELET WATCH WITH DIAMOND-SET INDEXES, DAY AND DATE, CIRCA 1971",
280 + "heading": null,
281 + "slug": "rolex-day-date-ref1803-a-white-gold-bracelet-watch-with-diamond-set-indexes-day-and-date-circa-1971",
282 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/26/25864145-13-3.jpg",
283 + "estimateLow": 100000,
284 + "estimateHigh": 200000,
285 + "hammerPrice": 110000,
286 + "hammerPremium": 140800,
287 + "startingBid": 85000,
288 + "currency": "HKD",
289 + "status": "SOLD",
290 + "hammerTime": "2026-09-03T08:11:00+00:00",
291 + "endDate": "2026-09-03T08:00:00+00:00",
292 + "department": "Watches",
293 + "categories": [],
294 + "isEnded": false,
295 + "isWithoutReserve": false
296 + },
297 + {
298 + "lotId": "1013",
299 + "lotUniqueId": "6184014",
300 + "lotNo": "1013",
301 + "title": "ROLEX | YACHT-MASTER 37, REF.268622, A PLATINUM AND STAINLESS STEEL WRISTWATCH WITH DATE, CIRCA 2023",
302 + "heading": null,
303 + "slug": "rolex-yacht-master-37-ref268622-a-platinum-and-stainless-steel-wristwatch-with-date-circa-2023",
304 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/26/25895221-1-4.jpg",
305 + "estimateLow": 70000,
306 + "estimateHigh": 140000,
307 + "hammerPrice": 80000,
308 + "hammerPremium": 102400,
309 + "startingBid": 60000,
310 + "currency": "HKD",
311 + "status": "SOLD",
312 + "hammerTime": "2026-09-03T08:12:00+00:00",
313 + "endDate": "2026-09-03T08:00:00+00:00",
314 + "department": "Watches",
315 + "categories": [],
316 + "isEnded": false,
317 + "isWithoutReserve": false
318 + },
319 + {
320 + "lotId": "1014",
321 + "lotUniqueId": "6184015",
322 + "lotNo": "1014",
323 + "title": "ROLEX | DATEJUST, REF.16014, A STAINLESS STEEL AND WHITE GOLD BRACELET WATCH WITH DATE, CIRCA 1980",
324 + "heading": null,
325 + "slug": "rolex-datejust-ref16014-a-stainless-steel-and-white-gold-bracelet-watch-with-date-circa-1980",
326 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902351-2-1.jpg",
327 + "estimateLow": 15000,
328 + "estimateHigh": 30000,
329 + "hammerPrice": 32000,
330 + "hammerPremium": 40960,
331 + "startingBid": 13000,
332 + "currency": "HKD",
333 + "status": "SOLD",
334 + "hammerTime": "2026-09-03T08:13:00+00:00",
335 + "endDate": "2026-09-03T08:00:00+00:00",
336 + "department": "Watches",
337 + "categories": [],
338 + "isEnded": false,
339 + "isWithoutReserve": false
340 + },
341 + {
342 + "lotId": "1015",
343 + "lotUniqueId": "6184016",
344 + "lotNo": "1015",
345 + "title": "ROLEX | CELLINI, REF.6623, A YELLOW GOLD BRACELET WATCH, CIRCA 1990",
346 + "heading": null,
347 + "slug": "rolex-cellini-ref6623-a-yellow-gold-bracelet-watch-circa-1990",
348 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25901935-7-2.jpg",
349 + "estimateLow": 70000,
350 + "estimateHigh": 140000,
351 + "hammerPrice": 75000,
352 + "hammerPremium": 96000,
353 + "startingBid": 60000,
354 + "currency": "HKD",
355 + "status": "SOLD",
356 + "hammerTime": "2026-09-03T08:14:00+00:00",
357 + "endDate": "2026-09-03T08:00:00+00:00",
358 + "department": "Watches",
359 + "categories": [],
360 + "isEnded": false,
361 + "isWithoutReserve": false
362 + },
363 + {
364 + "lotId": "1016",
365 + "lotUniqueId": "6184017",
366 + "lotNo": "1016",
367 + "title": "ROLEX | PEARLMASTER 34, REF.81318, A YELLOW GOLD AND DIAMOND-SET BRACELET WATCH WITH MOTHER-OF-PEARL DIAL, CIRCA 2009",
368 + "heading": null,
369 + "slug": "rolex-pearlmaster-34-ref81318-a-yellow-gold-and-diamond-set-bracelet-watch-with-mother-of-pearl-dial-circa-2009",
370 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25898045-5-1.jpg",
371 + "estimateLow": 60000,
372 + "estimateHigh": 120000,
373 + "hammerPrice": 130000,
374 + "hammerPremium": 166400,
375 + "startingBid": 50000,
376 + "currency": "HKD",
377 + "status": "SOLD",
378 + "hammerTime": "2026-09-03T08:15:00+00:00",
379 + "endDate": "2026-09-03T08:00:00+00:00",
380 + "department": "Watches",
381 + "categories": [],
382 + "isEnded": false,
383 + "isWithoutReserve": false
384 + },
385 + {
386 + "lotId": "1017",
387 + "lotUniqueId": "6184018",
388 + "lotNo": "1017",
389 + "title": "RICHARD MILLE | REF.RM07-01 \"RED LIP\", A RARE PINK GOLD SEMI-SKELETONISED WRISTWATCH WITH RED JASPER AND DIAMOND-SET DIAL, CIRCA 2016",
390 + "heading": "PROPERTY FROM AN IMPORTANT PRIVATE COLLECTOR\n重要私人珍藏",
391 + "slug": "richard-mille-refrm07-01-red-lip-a-rare-pink-gold-semi-skeletonised-wristwatch-with-red-jasper-and-diamond-set-dial-circa-2016",
392 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902455-1-1.jpg",
393 + "estimateLow": 700000,
394 + "estimateHigh": 1400000,
395 + "hammerPrice": 750000,
396 + "hammerPremium": 956500,
397 + "startingBid": 600000,
398 + "currency": "HKD",
399 + "status": "SOLD",
400 + "hammerTime": "2026-09-03T08:16:00+00:00",
401 + "endDate": "2026-09-03T08:00:00+00:00",
402 + "department": "Watches",
403 + "categories": [],
404 + "isEnded": false,
405 + "isWithoutReserve": false
406 + },
407 + {
408 + "lotId": "1018",
409 + "lotUniqueId": "6184019",
410 + "lotNo": "1018",
411 + "title": "PATEK PHILIPPE | NAUTILUS, REF.7010/1R-013, A PINK GOLD AND DIAMOND-SET BRACELET WATCH WITH DATE, CIRCA 2024",
412 + "heading": "PROPERTY FROM AN IMPORTANT PRIVATE COLLECTOR\n重要私人珍藏",
413 + "slug": "patek-philippe-nautilus-ref70101r-013-a-pink-gold-and-diamond-set-bracelet-watch-with-date-circa-2024",
414 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902455-3-1.jpg",
415 + "estimateLow": 480000,
416 + "estimateHigh": 900000,
417 + "hammerPrice": 700000,
418 + "hammerPremium": 893000,
419 + "startingBid": 400000,
420 + "currency": "HKD",
421 + "status": "SOLD",
422 + "hammerTime": "2026-09-03T08:17:00+00:00",
423 + "endDate": "2026-09-03T08:00:00+00:00",
424 + "department": "Watches",
425 + "categories": [],
426 + "isEnded": false,
427 + "isWithoutReserve": false
428 + },
429 + {
430 + "lotId": "1019",
431 + "lotUniqueId": "6184020",
432 + "lotNo": "1019",
433 + "title": "PATEK PHILIPPE | AQUANAUT, REF.5067A-001, A STAINLESS STEEL AND DIAMOND-SET WRISTWATCH WITH DATE, CIRCA 2015",
434 + "heading": "PROPERTY FROM AN IMPORTANT PRIVATE COLLECTOR\n重要私人珍藏",
435 + "slug": "patek-philippe-aquanaut-ref5067a-001-a-stainless-steel-and-diamond-set-wristwatch-with-date-circa-2015",
436 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902455-6-1.jpg",
437 + "estimateLow": 150000,
438 + "estimateHigh": 300000,
439 + "hammerPrice": 260000,
440 + "hammerPremium": 332800,
441 + "startingBid": 130000,
442 + "currency": "HKD",
443 + "status": "SOLD",
444 + "hammerTime": "2026-09-03T08:18:00+00:00",
445 + "endDate": "2026-09-03T08:00:00+00:00",
446 + "department": "Watches",
447 + "categories": [],
448 + "isEnded": false,
449 + "isWithoutReserve": false
450 + },
451 + {
452 + "lotId": "1020",
453 + "lotUniqueId": "6184021",
454 + "lotNo": "1020",
455 + "title": "PATEK PHILIPPE | CALATRAVA, REF.7200/200R-001, A PINK GOLD AND DIAMOND-SET WRISTWATCH, CIRCA 2023",
456 + "heading": "PROPERTY FROM AN IMPORTANT PRIVATE COLLECTOR\n重要私人珍藏",
457 + "slug": "patek-philippe-calatrava-ref7200200r-001-a-pink-gold-and-diamond-set-wristwatch-circa-2023",
458 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902455-5-1.jpg",
459 + "estimateLow": 100000,
460 + "estimateHigh": 200000,
461 + "hammerPrice": 120000,
462 + "hammerPremium": 153600,
463 + "startingBid": 90000,
464 + "currency": "HKD",
465 + "status": "SOLD",
466 + "hammerTime": "2026-09-03T08:19:00+00:00",
467 + "endDate": "2026-09-03T08:00:00+00:00",
468 + "department": "Watches",
469 + "categories": [],
470 + "isEnded": false,
471 + "isWithoutReserve": false
472 + },
473 + {
474 + "lotId": "1021",
475 + "lotUniqueId": "6184022",
476 + "lotNo": "1021",
477 + "title": "PATEK PHILIPPE | CALATRAVA TRAVEL TIME, REF.4934G-001, A FINE WHITE GOLD AND DIAMOND-SET DUAL TIME WRISTWATCH WITH MOTHER-OF-PEARL DIAL, CIRCA 2008",
478 + "heading": null,
479 + "slug": "patek-philippe-calatrava-travel-time-ref4934g-001-a-fine-white-gold-and-diamond-set-dual-time-wristwatch-with-mother-of-pearl-dial-circa-2008",
480 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25898045-4-1.jpg",
481 + "estimateLow": 110000,
482 + "estimateHigh": 220000,
483 + "hammerPrice": 110000,
484 + "hammerPremium": 140800,
485 + "startingBid": 80000,
486 + "currency": "HKD",
487 + "status": "SOLD",
488 + "hammerTime": "2026-09-03T08:20:00+00:00",
489 + "endDate": "2026-09-03T08:00:00+00:00",
490 + "department": "Watches",
491 + "categories": [],
492 + "isEnded": false,
493 + "isWithoutReserve": false
494 + },
495 + {
496 + "lotId": "1022",
497 + "lotUniqueId": "6184023",
498 + "lotNo": "1022",
499 + "title": "PATEK PHILIPPE | CALATRAVA PILOT TRAVEL TIME, REF.7234A-001, A RARE LIMITED EDITION STAINLESS STEEL DUAL TIME WRISTWATCH WITH DAY/NIGHT INDICATION AND DATE, MADE EXCLUSIVELY FOR THE SINGAPORE WATCH ART GRAND EXHIBITION, CIRCA 2020",
500 + "heading": "PROPERTY FROM AN IMPORTANT PRIVATE COLLECTOR\n重要私人珍藏",
501 + "slug": "patek-philippe-calatrava-pilot-travel-time-ref7234a-001-a-rare-limited-edition-stainless-steel-dual-time-wristwatch-with-daynight-indication-and-date-made-exclusively-for-the-singapore-watch-art-grand-exhibition-circa-2020",
502 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902455-2-1.jpg",
503 + "estimateLow": 200000,
504 + "estimateHigh": 400000,
505 + "hammerPrice": 280000,
506 + "hammerPremium": 358400,
507 + "startingBid": 170000,
508 + "currency": "HKD",
509 + "status": "SOLD",
510 + "hammerTime": "2026-09-03T08:21:00+00:00",
511 + "endDate": "2026-09-03T08:00:00+00:00",
512 + "department": "Watches",
513 + "categories": [],
514 + "isEnded": false,
515 + "isWithoutReserve": false
516 + },
517 + {
518 + "lotId": "1023",
519 + "lotUniqueId": "6184024",
520 + "lotNo": "1023",
521 + "title": "PATEK PHILIPPE | WORLD TIME, REF.7130G-014, A WHITE GOLD AND DIAMOND-SET WORLD TIME WRISTWATCH, CIRCA 2018",
522 + "heading": null,
523 + "slug": "patek-philippe-world-time-ref7130g-014-a-white-gold-and-diamond-set-world-time-wristwatch-circa-2018",
524 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902327-1-1.jpg",
525 + "estimateLow": 200000,
526 + "estimateHigh": 400000,
527 + "hammerPrice": 260000,
528 + "hammerPremium": 332800,
529 + "startingBid": 180000,
530 + "currency": "HKD",
531 + "status": "SOLD",
532 + "hammerTime": "2026-09-03T08:22:00+00:00",
533 + "endDate": "2026-09-03T08:00:00+00:00",
534 + "department": "Watches",
535 + "categories": [],
536 + "isEnded": false,
537 + "isWithoutReserve": false
538 + },
539 + {
540 + "lotId": "1024",
541 + "lotUniqueId": "6184025",
542 + "lotNo": "1024",
543 + "title": "PATEK PHILIPPE | GONDOLO SERATA, REF.4962/200R-010, A LADY'S PINK GOLD AND SPESSARTINE-SET WRISTWATCH WITH ZEBRA MOTIF, CIRCA 2025",
544 + "heading": null,
545 + "slug": "patek-philippe-gondolo-serata-ref4962200r-010-a-ladys-pink-gold-and-spessartine-set-wristwatch-with-zebra-motif-circa-2025",
546 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25850273-2-6.jpg",
547 + "estimateLow": 130000,
548 + "estimateHigh": 260000,
549 + "hammerPrice": 160000,
550 + "hammerPremium": 204800,
551 + "startingBid": 110000,
552 + "currency": "HKD",
553 + "status": "SOLD",
554 + "hammerTime": "2026-09-03T08:23:00+00:00",
555 + "endDate": "2026-09-03T08:00:00+00:00",
556 + "department": "Watches",
557 + "categories": [],
558 + "isEnded": false,
559 + "isWithoutReserve": false
560 + },
561 + {
562 + "lotId": "1025",
563 + "lotUniqueId": "6184026",
564 + "lotNo": "1025",
565 + "title": "PATEK PHILIPPE | GRAND COMPLICATIONS, REF.5320G-001, A WHITE GOLD PERPETUAL CALENDAR WRISTWATCH WITH MOON PHASES, LEAP YEAR AND DAY/NIGHT INDICATION, CIRCA 2022",
566 + "heading": null,
567 + "slug": "patek-philippe-grand-complications-ref5320g-001-a-white-gold-perpetual-calendar-wristwatch-with-moon-phases-leap-year-and-daynight-indication-circa-2022",
568 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/24/25902343-1-5.jpg",
569 + "estimateLow": 280000,
570 + "estimateHigh": 560000,
571 + "hammerPrice": 380000,
572 + "hammerPremium": 486400,
573 + "startingBid": 240000,
574 + "currency": "HKD",
575 + "status": "SOLD",
576 + "hammerTime": "2026-09-03T08:24:00+00:00",
577 + "endDate": "2026-09-03T08:00:00+00:00",
578 + "department": "Watches",
579 + "categories": [],
580 + "isEnded": false,
581 + "isWithoutReserve": false
582 + },
583 + {
584 + "lotId": "1026",
585 + "lotUniqueId": "6184027",
586 + "lotNo": "1026",
587 + "title": "[NO RESERVE] PATEK PHILIPPE | A SET OF ACCESSORIES INCLUDING A WATCH CYLINDER, A LEATHER TRAVEL CASE AND LIMOGES PORCELAIN DISH",
588 + "heading": null,
589 + "slug": "no-reserve-patek-philippe-a-set-of-accessories-including-a-watch-cylinder-a-leather-travel-case-and-limoges-porcelain-dish",
590 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25877737-1-4.jpg",
591 + "estimateLow": 15000,
592 + "estimateHigh": 30000,
593 + "hammerPrice": 4200,
594 + "hammerPremium": 5376,
595 + "startingBid": 3000,
596 + "currency": "HKD",
597 + "status": "SOLD",
598 + "hammerTime": "2026-09-03T08:25:00+00:00",
599 + "endDate": "2026-09-03T08:00:00+00:00",
600 + "department": "Watches",
601 + "categories": [],
602 + "isEnded": false,
603 + "isWithoutReserve": true
604 + },
605 + {
606 + "lotId": "1027",
607 + "lotUniqueId": "6184028",
608 + "lotNo": "1027",
609 + "title": "A.LANGE & SÖHNE | LANGE 1 SOIRÉE, REF.110.041, A SUPER RARE LIMITED PRODUCTION PLATINUM WRISTWATCH WITH TAHITIAN MOTHER-OF-PEARL DIAL AND DATE, CIRCA 2003",
610 + "heading": null,
611 + "slug": "alange-and-sohne-lange-1-soiree-ref110041-a-super-rare-limited-production-platinum-wristwatch-with-tahitian-mother-of-pearl-dial-and-date-circa-2003",
612 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902865-12-1.jpg",
613 + "estimateLow": 400000,
614 + "estimateHigh": 800000,
615 + "hammerPrice": 4000000,
616 + "hammerPremium": 5084000,
617 + "startingBid": 360000,
618 + "currency": "HKD",
619 + "status": "SOLD",
620 + "hammerTime": "2026-09-03T08:26:00+00:00",
621 + "endDate": "2026-09-03T08:00:00+00:00",
622 + "department": "Watches",
623 + "categories": [],
624 + "isEnded": false,
625 + "isWithoutReserve": false
626 + },
627 + {
628 + "lotId": "1028",
629 + "lotUniqueId": "6184029",
630 + "lotNo": "1028",
631 + "title": "GLASHÜTTE ORIGINAL | PANOMATIC TOURBILLON, REF.93-01-01-01-04, A LIMITED EDITION PINK GOLD TOURBILLON WRISTWATCH WITH DATE, CIRCA 2014",
632 + "heading": null,
633 + "slug": "glashutte-original-panomatic-tourbillon-ref93-01-01-01-04-a-limited-edition-pink-gold-tourbillon-wristwatch-with-date-circa-2014",
634 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25907584-3-1.jpg",
635 + "estimateLow": 120000,
636 + "estimateHigh": 240000,
637 + "hammerPrice": 140000,
638 + "hammerPremium": 179200,
639 + "startingBid": 100000,
640 + "currency": "HKD",
641 + "status": "SOLD",
642 + "hammerTime": "2026-09-03T08:27:00+00:00",
643 + "endDate": "2026-09-03T08:00:00+00:00",
644 + "department": "Watches",
645 + "categories": [],
646 + "isEnded": false,
647 + "isWithoutReserve": false
648 + },
649 + {
650 + "lotId": "1029",
651 + "lotUniqueId": "6184030",
652 + "lotNo": "1029",
653 + "title": "GLASHÜTTE ORIGINAL | PANOMATIC CHRONO, REF.95-01-03-03-04, A LIMITED EDITION PLATINUM CHRONOGRAPH WRISTWATCH WITH DATE, CIRCA 2005",
654 + "heading": null,
655 + "slug": "glashutte-original-panomatic-chrono-ref95-01-03-03-04-a-limited-edition-platinum-chronograph-wristwatch-with-date-circa-2005",
656 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25907584-4-1.jpg",
657 + "estimateLow": 60000,
658 + "estimateHigh": 120000,
659 + "hammerPrice": 110000,
660 + "hammerPremium": 140800,
661 + "startingBid": 48000,
662 + "currency": "HKD",
663 + "status": "SOLD",
664 + "hammerTime": "2026-09-03T08:28:00+00:00",
665 + "endDate": "2026-09-03T08:00:00+00:00",
666 + "department": "Watches",
667 + "categories": [],
668 + "isEnded": false,
669 + "isWithoutReserve": false
670 + },
671 + {
672 + "lotId": "1030",
673 + "lotUniqueId": "6184031",
674 + "lotNo": "1030",
675 + "title": "GLASHÜTTE ORIGINAL | SENATOR CHRONOGRAPH \"100 JAHRE WEMPE\", REF.49-11-02-02-04, A LIMITED EDITION STAINLESS STEEL CHRONOGRAPH WRISTWATCH, CIRCA 2006",
676 + "heading": null,
677 + "slug": "glashutte-original-senator-chronograph-100-jahre-wempe-ref49-11-02-02-04-a-limited-edition-stainless-steel-chronograph-wristwatch-circa-2006",
678 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25895855-2-1.jpg",
679 + "estimateLow": 34000,
680 + "estimateHigh": 68000,
681 + "hammerPrice": 34000,
682 + "hammerPremium": 43520,
683 + "startingBid": 30000,
684 + "currency": "HKD",
685 + "status": "SOLD",
686 + "hammerTime": "2026-09-03T08:29:00+00:00",
687 + "endDate": "2026-09-03T08:00:00+00:00",
688 + "department": "Watches",
689 + "categories": [],
690 + "isEnded": false,
691 + "isWithoutReserve": false
692 + },
693 + {
694 + "lotId": "1031",
695 + "lotUniqueId": "6184032",
696 + "lotNo": "1031",
697 + "title": "IWC | PORTUGUESE, REF.IW500106, A WHITE GOLD WRISTWATCH WITH POWER RESERVE INDICATOR AND DATE, CIRCA 2020",
698 + "heading": null,
699 + "slug": "iwc-portuguese-refiw500106-a-white-gold-wristwatch-with-power-reserve-indicator-and-date-circa-2020",
700 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25907584-1-1.jpg",
701 + "estimateLow": 50000,
702 + "estimateHigh": 100000,
703 + "hammerPrice": 50000,
704 + "hammerPremium": 64000,
705 + "startingBid": 40000,
706 + "currency": "HKD",
707 + "status": "SOLD",
708 + "hammerTime": "2026-09-03T08:30:00+00:00",
709 + "endDate": "2026-09-03T08:00:00+00:00",
710 + "department": "Watches",
711 + "categories": [],
712 + "isEnded": false,
713 + "isWithoutReserve": false
714 + },
715 + {
716 + "lotId": "1032",
717 + "lotUniqueId": "6184033",
718 + "lotNo": "1032",
719 + "title": "JACOB & CO | THE WORLD IS YOURS DUAL TIME, REF.DT100.10.AA.AA.A, A BRAND NEW STAINLESS STEEL DUAL TIME ZONE WRISTWATCH, CIRCA 2026",
720 + "heading": null,
721 + "slug": "jacob-and-co-the-world-is-yours-dual-time-refdt10010aaaaa-a-brand-new-stainless-steel-dual-time-zone-wristwatch-circa-2026",
722 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/26/25832097-18-7.jpg",
723 + "estimateLow": 90000,
724 + "estimateHigh": 180000,
725 + "hammerPrice": 120000,
726 + "hammerPremium": 153600,
727 + "startingBid": 80000,
728 + "currency": "HKD",
729 + "status": "SOLD",
730 + "hammerTime": "2026-09-03T08:31:00+00:00",
731 + "endDate": "2026-09-03T08:00:00+00:00",
732 + "department": "Watches",
733 + "categories": [],
734 + "isEnded": false,
735 + "isWithoutReserve": false
736 + },
737 + {
738 + "lotId": "1033",
739 + "lotUniqueId": "6184034",
740 + "lotNo": "1033",
741 + "title": "VACHERON CONSTANTIN | PATRIMONY RETROGRADE DAY DATE, REF.86020/000R-9239, A PINK GOLD WRISTWATCH WITH RETROGRADE DAY AND DATE, CIRCA 2014",
742 + "heading": null,
743 + "slug": "vacheron-constantin-patrimony-retrograde-day-date-ref86020000r-9239-a-pink-gold-wristwatch-with-retrograde-day-and-date-circa-2014",
744 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902865-11-1.jpg",
745 + "estimateLow": 120000,
746 + "estimateHigh": 240000,
747 + "hammerPrice": 170000,
748 + "hammerPremium": 217600,
749 + "startingBid": 100000,
750 + "currency": "HKD",
751 + "status": "SOLD",
752 + "hammerTime": "2026-09-03T08:32:00+00:00",
753 + "endDate": "2026-09-03T08:00:00+00:00",
754 + "department": "Watches",
755 + "categories": [],
756 + "isEnded": false,
757 + "isWithoutReserve": false
758 + },
759 + {
760 + "lotId": "1034",
761 + "lotUniqueId": "6184035",
762 + "lotNo": "1034",
763 + "title": "VACHERON CONSTANTIN | PATRIMONY MOON PHASE RETROGRADE DATE, REF.4010U/000G-H070, A NEW OLD STOCK WHITE GOLD WRISTWATCH WITH RETROGRADE DATE AND MOON PHASES, CIRCA 2025",
764 + "heading": null,
765 + "slug": "vacheron-constantin-patrimony-moon-phase-retrograde-date-ref4010u000g-h070-a-new-old-stock-white-gold-wristwatch-with-retrograde-date-and-moon-phases-circa-2025",
766 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25901935-12-1.jpg",
767 + "estimateLow": 100000,
768 + "estimateHigh": 200000,
769 + "hammerPrice": 190000,
770 + "hammerPremium": 243200,
771 + "startingBid": 90000,
772 + "currency": "HKD",
773 + "status": "SOLD",
774 + "hammerTime": "2026-09-03T08:33:00+00:00",
775 + "endDate": "2026-09-03T08:00:00+00:00",
776 + "department": "Watches",
777 + "categories": [],
778 + "isEnded": false,
779 + "isWithoutReserve": false
780 + },
781 + {
782 + "lotId": "1035",
783 + "lotUniqueId": "6184036",
784 + "lotNo": "1035",
785 + "title": "VACHERON CONSTANTIN | MALTE GRAND CLASSIQUE, REF.81000/000J, A YELLOW GOLD WRISTWATCH WITH DIAMOND-SET INDEXES, CIRCA 2008",
786 + "heading": null,
787 + "slug": "vacheron-constantin-malte-grand-classique-ref81000000j-a-yellow-gold-wristwatch-with-diamond-set-indexes-circa-2008",
788 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25895855-1-1.jpg",
789 + "estimateLow": 46000,
790 + "estimateHigh": 92000,
791 + "hammerPrice": 48000,
792 + "hammerPremium": 61440,
793 + "startingBid": 42000,
794 + "currency": "HKD",
795 + "status": "SOLD",
796 + "hammerTime": "2026-09-03T08:34:00+00:00",
797 + "endDate": "2026-09-03T08:00:00+00:00",
798 + "department": "Watches",
799 + "categories": [],
800 + "isEnded": false,
801 + "isWithoutReserve": false
802 + },
803 + {
804 + "lotId": "1036",
805 + "lotUniqueId": "6184037",
806 + "lotNo": "1036",
807 + "title": "VACHERON CONSTANTIN | PATRIMONY, REF.34170/000J-3, A YELLOW GOLD WRISTWATCH, CIRCA 1994",
808 + "heading": null,
809 + "slug": "vacheron-constantin-patrimony-ref34170000j-3-a-yellow-gold-wristwatch-circa-1994",
810 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25901796-3-1.jpg",
811 + "estimateLow": 34000,
812 + "estimateHigh": 68000,
813 + "hammerPrice": 42000,
814 + "hammerPremium": 53760,
815 + "startingBid": 30000,
816 + "currency": "HKD",
817 + "status": "SOLD",
818 + "hammerTime": "2026-09-03T08:35:00+00:00",
819 + "endDate": "2026-09-03T08:00:00+00:00",
820 + "department": "Watches",
821 + "categories": [],
822 + "isEnded": false,
823 + "isWithoutReserve": false
824 + },
825 + {
826 + "lotId": "1037",
827 + "lotUniqueId": "6184038",
828 + "lotNo": "1037",
829 + "title": "[NO RESERVE] BLANCPAIN | VILLERET ULTRA SLIM, REF.0072-1418-55, A YELLOW GOLD WRISTWATCH, CIRCA 1990",
830 + "heading": null,
831 + "slug": "no-reserve-blancpain-villeret-ultra-slim-ref0072-1418-55-a-yellow-gold-wristwatch-circa-1990",
832 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25907584-6-1.jpg",
833 + "estimateLow": 20000,
834 + "estimateHigh": 40000,
835 + "hammerPrice": 24000,
836 + "hammerPremium": 30720,
837 + "startingBid": 10000,
838 + "currency": "HKD",
839 + "status": "SOLD",
840 + "hammerTime": "2026-09-03T08:36:00+00:00",
841 + "endDate": "2026-09-03T08:00:00+00:00",
842 + "department": "Watches",
843 + "categories": [],
844 + "isEnded": false,
845 + "isWithoutReserve": true
846 + },
847 + {
848 + "lotId": "1038",
849 + "lotUniqueId": "6184039",
850 + "lotNo": "1038",
851 + "title": "GIRARD-PERREGAUX | GYROMATIC, A 14K YELLOW GOLD WRISTWATCH, CIRCA 1960",
852 + "heading": null,
853 + "slug": "girard-perregaux-gyromatic-a-14k-yellow-gold-wristwatch-circa-1960",
854 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25901796-1-1.jpg",
855 + "estimateLow": 12000,
856 + "estimateHigh": 24000,
857 + "hammerPrice": 12000,
858 + "hammerPremium": 15360,
859 + "startingBid": 10000,
860 + "currency": "HKD",
861 + "status": "SOLD",
862 + "hammerTime": "2026-09-03T08:37:00+00:00",
863 + "endDate": "2026-09-03T08:00:00+00:00",
864 + "department": "Watches",
865 + "categories": [],
866 + "isEnded": false,
867 + "isWithoutReserve": false
868 + },
869 + {
870 + "lotId": "1039",
871 + "lotUniqueId": "6184040",
872 + "lotNo": "1039",
873 + "title": "CHOPARD | POINÇON DE GENÈVE 125TH ANNIVERSARY EDITION, REF.161932-5001, A LIMITED EDITION PINK GOLD WRISTWATCH WITH DATE, CIRCA 2011",
874 + "heading": null,
875 + "slug": "chopard-poincon-de-geneve-125th-anniversary-edition-ref161932-5001-a-limited-edition-pink-gold-wristwatch-with-date-circa-2011",
876 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/26/25896383-1-9.jpg",
877 + "estimateLow": 55000,
878 + "estimateHigh": 110000,
879 + "hammerPrice": 60000,
880 + "hammerPremium": 76800,
881 + "startingBid": 48000,
882 + "currency": "HKD",
883 + "status": "SOLD",
884 + "hammerTime": "2026-09-03T08:38:00+00:00",
885 + "endDate": "2026-09-03T08:00:00+00:00",
886 + "department": "Watches",
887 + "categories": [],
888 + "isEnded": false,
889 + "isWithoutReserve": false
890 + },
891 + {
892 + "lotId": "1040",
893 + "lotUniqueId": "6184041",
894 + "lotNo": "1040",
895 + "title": "[NO RESERVE] CHOPARD | MILLIE MIGLIA, REF.8407, A LIMITED EDITION TITANIUM CHRONOGRAPH WRISTWATCH WITH DATE, CIRCA 2001",
896 + "heading": null,
897 + "slug": "no-reserve-chopard-millie-miglia-ref8407-a-limited-edition-titanium-chronograph-wristwatch-with-date-circa-2001",
898 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25902397-2-1.jpg",
899 + "estimateLow": 20000,
900 + "estimateHigh": 40000,
901 + "hammerPrice": 20000,
902 + "hammerPremium": 25600,
903 + "startingBid": 10000,
904 + "currency": "HKD",
905 + "status": "SOLD",
906 + "hammerTime": "2026-09-03T08:39:00+00:00",
907 + "endDate": "2026-09-03T08:00:00+00:00",
908 + "department": "Watches",
909 + "categories": [],
910 + "isEnded": false,
911 + "isWithoutReserve": true
912 + },
913 + {
914 + "lotId": "1041",
915 + "lotUniqueId": "6184042",
916 + "lotNo": "1041",
917 + "title": "AUDEMARS PIGUET | ROYAL OAK OFFSHORE \"JUAN PABLO MONTOYA, REF.26030IO.OO.D001IN.01, A LIMITED EDITION TITANIUM AND CARBON FIBRE CHRONOGRAPH WRISTWATCH WITH DATE, CIRCA 2005",
918 + "heading": null,
919 + "slug": "audemars-piguet-royal-oak-offshore-juan-pablo-montoya-ref26030ioood001in01-a-limited-edition-titanium-and-carbon-fibre-chronograph-wristwatch-with-date-circa-2005",
920 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25898045-3-1.jpg",
921 + "estimateLow": 90000,
922 + "estimateHigh": 180000,
923 + "hammerPrice": 140000,
924 + "hammerPremium": 179200,
925 + "startingBid": 80000,
926 + "currency": "HKD",
927 + "status": "SOLD",
928 + "hammerTime": "2026-09-03T08:40:00+00:00",
929 + "endDate": "2026-09-03T08:00:00+00:00",
930 + "department": "Watches",
931 + "categories": [],
932 + "isEnded": false,
933 + "isWithoutReserve": false
934 + },
935 + {
936 + "lotId": "1042",
937 + "lotUniqueId": "6184043",
938 + "lotNo": "1042",
939 + "title": "AUDEMARS PIGUET | MILLENARY, REF. 77301OR.ZZ.D015CR.01, A PINK GOLD AND DIAMOND-SET WRISTWATCH WITH MOTHER-OF-PEARL DIAL, CIRCA 2013",
940 + "heading": null,
941 + "slug": "audemars-piguet-millenary-ref-77301orzzd015cr01-a-pink-gold-and-diamond-set-wristwatch-with-mother-of-pearl-dial-circa-2013",
942 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25902865-8-3.jpg",
943 + "estimateLow": 65000,
944 + "estimateHigh": 130000,
945 + "hammerPrice": 70000,
946 + "hammerPremium": 89600,
947 + "startingBid": 55000,
948 + "currency": "HKD",
949 + "status": "SOLD",
950 + "hammerTime": "2026-09-03T08:41:00+00:00",
951 + "endDate": "2026-09-03T08:00:00+00:00",
952 + "department": "Watches",
953 + "categories": [],
954 + "isEnded": false,
955 + "isWithoutReserve": false
956 + },
957 + {
958 + "lotId": "1043",
959 + "lotUniqueId": "6184044",
960 + "lotNo": "1043",
961 + "title": "AUDEMARS PIGUET | MILLENARY CHRONOGRAPH, REF.25822OR, A PINK GOLD CHRONOGRAPH WRISTWATCH WITH DATE AND TELEMETER SCALE, CIRCA 2004",
962 + "heading": null,
963 + "slug": "audemars-piguet-millenary-chronograph-ref25822or-a-pink-gold-chronograph-wristwatch-with-date-and-telemeter-scale-circa-2004",
964 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25901935-13-1.jpg",
965 + "estimateLow": 50000,
966 + "estimateHigh": 100000,
967 + "hammerPrice": 70000,
968 + "hammerPremium": 89600,
969 + "startingBid": 46000,
970 + "currency": "HKD",
971 + "status": "SOLD",
972 + "hammerTime": "2026-09-03T08:42:00+00:00",
973 + "endDate": "2026-09-03T08:00:00+00:00",
974 + "department": "Watches",
975 + "categories": [],
976 + "isEnded": false,
977 + "isWithoutReserve": false
978 + },
979 + {
980 + "lotId": "1044",
981 + "lotUniqueId": "6184045",
982 + "lotNo": "1044",
983 + "title": "AUDEMARS PIGUET | MILLENARY, REF.26018ST.ZZ.D007CR.01, A STAINLESS STEEL AND DIAMOND-SET CHRONOGRAPH WRISTWATCH WITH DATE, CIRCA 2009",
984 + "heading": null,
985 + "slug": "audemars-piguet-millenary-ref26018stzzd007cr01-a-stainless-steel-and-diamond-set-chronograph-wristwatch-with-date-circa-2009",
986 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/26/25860654-6-4.jpg",
987 + "estimateLow": 22000,
988 + "estimateHigh": 44000,
989 + "hammerPrice": 32000,
990 + "hammerPremium": 40960,
991 + "startingBid": 19000,
992 + "currency": "HKD",
993 + "status": "SOLD",
994 + "hammerTime": "2026-09-03T08:43:00+00:00",
995 + "endDate": "2026-09-03T08:00:00+00:00",
996 + "department": "Watches",
997 + "categories": [],
998 + "isEnded": false,
999 + "isWithoutReserve": false
1000 + },
1001 + {
1002 + "lotId": "1045",
1003 + "lotUniqueId": "6184046",
1004 + "lotNo": "1045",
1005 + "title": "AUDEMARS PIGUET | MERIDIAN, BA.56340.756, A YELLOW GOLD BRACELET WATCH WITH DATE, CIRCA 1988",
1006 + "heading": null,
1007 + "slug": "audemars-piguet-meridian-ba56340756-a-yellow-gold-bracelet-watch-with-date-circa-1988",
1008 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/21/25902865-7-2.jpg",
1009 + "estimateLow": 40000,
1010 + "estimateHigh": 80000,
1011 + "hammerPrice": 65000,
1012 + "hammerPremium": 83200,
1013 + "startingBid": 36000,
1014 + "currency": "HKD",
1015 + "status": "SOLD",
1016 + "hammerTime": "2026-09-03T08:44:00+00:00",
1017 + "endDate": "2026-09-03T08:00:00+00:00",
1018 + "department": "Watches",
1019 + "categories": [],
1020 + "isEnded": false,
1021 + "isWithoutReserve": false
1022 + },
1023 + {
1024 + "lotId": "1046",
1025 + "lotUniqueId": "6184047",
1026 + "lotNo": "1046",
1027 + "title": "AUDEMARS PIGUET | A FINE WHITE GOLD BRACELET WATCH WITH DIAMOND-SET INDEXES AND HANDS, CIRCA 1975",
1028 + "heading": null,
1029 + "slug": "audemars-piguet-a-fine-white-gold-bracelet-watch-with-diamond-set-indexes-and-hands-circa-1975",
1030 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25901935-9-1.jpg",
1031 + "estimateLow": 44000,
1032 + "estimateHigh": 85000,
1033 + "hammerPrice": 70000,
1034 + "hammerPremium": 89600,
1035 + "startingBid": 40000,
1036 + "currency": "HKD",
1037 + "status": "SOLD",
1038 + "hammerTime": "2026-09-03T08:45:00+00:00",
1039 + "endDate": "2026-09-03T08:00:00+00:00",
1040 + "department": "Watches",
1041 + "categories": [],
1042 + "isEnded": false,
1043 + "isWithoutReserve": false
1044 + },
1045 + {
1046 + "lotId": "1047",
1047 + "lotUniqueId": "6184048",
1048 + "lotNo": "1047",
1049 + "title": "PIAGET | REF.612773, A YELLOW GOLD DUAL TIME BRACELET WATCH, CIRCA 1970",
1050 + "heading": null,
1051 + "slug": "piaget-ref612773-a-yellow-gold-dual-time-bracelet-watch-circa-1970",
1052 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25903281-6-1.jpg",
1053 + "estimateLow": 40000,
1054 + "estimateHigh": 80000,
1055 + "hammerPrice": 90000,
1056 + "hammerPremium": 115200,
1057 + "startingBid": 36000,
1058 + "currency": "HKD",
1059 + "status": "SOLD",
1060 + "hammerTime": "2026-09-03T08:46:00+00:00",
1061 + "endDate": "2026-09-03T08:00:00+00:00",
1062 + "department": "Watches",
1063 + "categories": [],
1064 + "isEnded": false,
1065 + "isWithoutReserve": false
1066 + },
1067 + {
1068 + "lotId": "1048",
1069 + "lotUniqueId": "6184049",
1070 + "lotNo": "1048",
1071 + "title": "JAEGER-LECOULTRE | MASTER CONTROL GEOGRAPHIC, REF.142.8.92, A STAINLESS STEEL WORLD TIME BRACELET WATCH WITH DATE, DAY/NIGHT AND POWER RESERVE INDICATOR, CIRCA 2010",
1072 + "heading": null,
1073 + "slug": "jaeger-lecoultre-master-control-geographic-ref142892-a-stainless-steel-world-time-bracelet-watch-with-date-daynight-and-power-reserve-indicator-circa-2010",
1074 + "imageUrl": "https://images3.bonhams.com/image?src=Images/live/2026-08/20/25903281-1-1.jpg",
1075 + "estimateLow": 30000,
1076 + "estimateHigh": 60000,
1077 + "hammerPrice": 32000,
1078 + "hammerPremium": 40960,
1079 + "startingBid": 26000,
1080 + "currency": "HKD",
1081 + "status": "SOLD",
1082 + "hammerTime": "2026-09-03T08:47:00+00:00",
1083 + "endDate": "2026-09-03T08:00:00+00:00",
1084 + "department": "Watches",
1085 + "categories": [],
1086 + "isEnded": false,
1087 + "isWithoutReserve": false
1088 + }
1089 + ]
1090 + },
1091 + "fetchedAt": "2026-09-07T06:06:01.837Z"
1092 + },
1093 + "expect": {
1094 + "minCount": 1,
1095 + "kinds": [
1096 + "sale"
1097 + ],
1098 + "first": {
1099 + "kind": "sale",
1100 + "auctionHouse": "Bonhams",
1101 + "currency": "HKD"
1102 + }
1103 + },
1104 + "note": "Captured live by connectors/api/_auction-lib/smoke.ts on 2026-09-07 (48 records from this raw page).",
1105 + "capturedAt": "2026-09-07T06:06:01.850Z"
1106 +}
\ No newline at end of file
added data/fixtures/catawiki/seeded-1.json +110 −0
@@ -0,0 +1,110 @@
1 +{
2 + "raw": {
3 + "url": "https://www.catawiki.com/en/l/106351561",
4 + "externalId": "106351561",
5 + "kind": "sale",
6 + "engine": "scrapfly",
7 + "httpStatus": 200,
8 + "payload": {
9 + "kind": "lot",
10 + "seedHint": "unknown",
11 + "id": 106351561,
12 + "url": "https://www.catawiki.com/en/l/106351561",
13 + "title": "Figure - An antique devotional figure - 29 cm - Wood",
14 + "subtitle": "South America - 1750-1800 - Fair condition - heavily used & with possibly minor parts missing",
15 + "description": "This item is an antique hand-carved wooden santo (devotional figure), characteristic of Latin American or Spanish colonial folk art featuring weathered polychrome paint and a distinct headdress. The item is beautifully designed and made with great care and detail. We feel that the piece is in overall fair unrestored condition with great original patina Dimensions 29cm height 11cm width 8cm depth Item will be shipped with registered shipping ",
16 + "images": [
17 + "https://assets.catawiki.nl/assets/2026/8/25/7/1/f/71f84eeb-ccb7-4a5d-aba7-169e2bd38403.jpg",
18 + "https://assets.catawiki.nl/assets/2026/8/25/7/f/0/7f002a45-dc06-4117-80fa-ecaee5bcf741.jpg",
19 + "https://assets.catawiki.nl/assets/2026/8/25/9/6/8/96893860-8591-4306-be24-3fc7c308c0bd.jpg"
20 + ],
21 + "categoryId": 481,
22 + "categoryUrl": "https://www.catawiki.com/en/c/481-antique-religious-decor",
23 + "auction": {
24 + "id": 1244222,
25 + "title": "Private Chapel Auction",
26 + "url": "https://www.catawiki.com/en/a/1244222-private-chapel-auction",
27 + "status": "closed",
28 + "startAt": "2026-08-27T16:00:00Z",
29 + "closeAt": "2026-09-03T18:00:00Z",
30 + "closedAt": "2026-09-03T19:21:11Z",
31 + "categories": [
32 + "Interiors & Decorations",
33 + "Antiques & Classic Furniture",
34 + "Antique Religious Decor"
35 + ],
36 + "lotCount": 75
37 + },
38 + "specs": [
39 + {
40 + "name": "Era",
41 + "value": "1400-1900"
42 + },
43 + {
44 + "name": "Number of objects",
45 + "value": "1"
46 + },
47 + {
48 + "name": "Title",
49 + "value": "An antique devotional figure - 29 cm"
50 + },
51 + {
52 + "name": "Country of origin",
53 + "value": "South America"
54 + },
55 + {
56 + "name": "Material",
57 + "value": "Wood"
58 + },
59 + {
60 + "name": "Condition",
61 + "value": "Fair condition - heavily used & with possibly minor parts missing"
62 + },
63 + {
64 + "name": "Height",
65 + "value": "29 cm"
66 + },
67 + {
68 + "name": "Width",
69 + "value": "11 cm"
70 + },
71 + {
72 + "name": "Depth",
73 + "value": "8 cm"
74 + },
75 + {
76 + "name": "Estimated period",
77 + "value": "1750-1800"
78 + }
79 + ],
80 + "estimateMinEur": 200,
81 + "estimateMaxEur": 250,
82 + "sellerCountry": "NL",
83 + "sellerName": "Artichoke Art & Antique",
84 + "sellerIsPro": true,
85 + "bidding": {
86 + "closed": true,
87 + "sold": true,
88 + "finalBidEur": 60,
89 + "biddingStartTime": 1787846400000,
90 + "biddingEndTime": 1788459500000,
91 + "bidCount": 525,
92 + "reservePriceMet": null
93 + }
94 + },
95 + "fetchedAt": "2026-09-07T06:02:42.001Z"
96 + },
97 + "expect": {
98 + "minCount": 1,
99 + "kinds": [
100 + "sale"
101 + ],
102 + "first": {
103 + "kind": "sale",
104 + "auctionHouse": "Catawiki",
105 + "currency": "EUR"
106 + }
107 + },
108 + "note": "Captured live by connectors/api/_auction-lib/smoke.ts on 2026-09-07 (1 records from this raw page).",
109 + "capturedAt": "2026-09-07T06:02:42.007Z"
110 +}
\ No newline at end of file
added data/fixtures/catawiki/seeded-2.json +674 −0
@@ -0,0 +1,674 @@
1 +{
2 + "raw": {
3 + "url": "https://www.catawiki.com/en/a/1263062-vintage-watches-auction",
4 + "externalId": "a1263062",
5 + "kind": "auction_lot",
6 + "engine": "scrapfly",
7 + "httpStatus": 200,
8 + "payload": {
9 + "kind": "auction_lots",
10 + "seedHint": "unknown",
11 + "auction": {
12 + "id": 1263062,
13 + "title": "Vintage Watches Auction",
14 + "url": "https://www.catawiki.com/en/a/1263062-vintage-watches-auction",
15 + "status": "open_now",
16 + "startAt": "2026-09-01T16:00:00Z",
17 + "closeAt": "2026-09-08T17:00:00Z",
18 + "closedAt": null,
19 + "categories": [
20 + "Watches, Pens & Lighters",
21 + "Watches",
22 + "Vintage Watches"
23 + ],
24 + "lotCount": 59
25 + },
26 + "lots": [
27 + {
28 + "id": 106431494,
29 + "title": "Lanco - Swiss - Mechanical - mens - gold plated - Dress Watch – 1960s - No reserve price - Men - 1960-1969 ",
30 + "subtitle": "Manual winding - Gold-plated",
31 + "url": "https://www.catawiki.com/en/l/106431494-lanco-swiss-mechanical-mens-gold-plated-dress-watch-1960s-no-reserve-price-men-1960-1969",
32 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/9/c/5/9c501190-df47-477a-b73c-8e64f4c93e43.jpg",
33 + "reservePriceSet": false,
34 + "biddingStartTime": null
35 + },
36 + {
37 + "id": 106448188,
38 + "title": "Sicura - Submarine 200 - [cal. EB 8021] - No reserve price - 23 Jewels - Men - 1960",
39 + "subtitle": "Manual winding - Chromed",
40 + "url": "https://www.catawiki.com/en/l/106448188-sicura-submarine-200-cal-eb-8021-no-reserve-price-23-jewels-men-1960",
41 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/4/f/c/4fc26c71-c774-4141-bc3d-cacaa60b2be2.jpg",
42 + "reservePriceSet": false,
43 + "biddingStartTime": null
44 + },
45 + {
46 + "id": 106429428,
47 + "title": "Unitas Extra - Small Second - No reserve price - Men - 1950-1959 ",
48 + "subtitle": "Manual winding - Stainless steel",
49 + "url": "https://www.catawiki.com/en/l/106429428-unitas-extra-small-second-no-reserve-price-men-1950-1959",
50 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/9/9/d/99d73527-babf-4025-a9fa-535fc8449850.jpg",
51 + "reservePriceSet": false,
52 + "biddingStartTime": null
53 + },
54 + {
55 + "id": 106431311,
56 + "title": "Jivana - Swiss - Mechanical - mens - gold plated - Dress Watch – 1960s - No reserve price - Men - 1960-1969 ",
57 + "subtitle": "Manual winding - Gold-plated",
58 + "url": "https://www.catawiki.com/en/l/106431311-jivana-swiss-mechanical-mens-gold-plated-dress-watch-1960s-no-reserve-price-men-1960-1969",
59 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/f/7/0/f707131b-4f4a-4f34-b1fe-56775e71c1a8.jpg",
60 + "reservePriceSet": false,
61 + "biddingStartTime": null
62 + },
63 + {
64 + "id": 106402795,
65 + "title": "Arctos Elite - Classic Calendar 21Jewels - No reserve price - 2187 - Men - 1960-1969 ",
66 + "subtitle": "Manual winding - Stainless steel, Metal, Gold-plated",
67 + "url": "https://www.catawiki.com/en/l/106402795-arctos-elite-classic-calendar-21jewels-no-reserve-price-2187-men-1960-1969",
68 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/27/f/2/7/f27ba240-df0c-4f80-9c52-29a14c42ffde.jpg",
69 + "reservePriceSet": false,
70 + "biddingStartTime": null
71 + },
72 + {
73 + "id": 106431922,
74 + "title": "Cimex - Ebauche Suisse - Mechanical - mens - gold plated - Dress Watch – 1960s - No reserve price - Men - 1960-1969 ",
75 + "subtitle": "Manual winding - Gold-plated",
76 + "url": "https://www.catawiki.com/en/l/106431922-cimex-ebauche-suisse-mechanical-mens-gold-plated-dress-watch-1960s-no-reserve-price-men-1960-1969",
77 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/6/e/b/6eba85e7-bc46-4bf1-965a-d130aa862c21.jpg",
78 + "reservePriceSet": false,
79 + "biddingStartTime": null
80 + },
81 + {
82 + "id": 106433826,
83 + "title": "Sicura - Signal - No reserve price - Men - 1970-1979 ",
84 + "subtitle": "Manual winding - Stainless steel",
85 + "url": "https://www.catawiki.com/en/l/106433826-sicura-signal-no-reserve-price-men-1970-1979",
86 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/1/7/0/17077cdd-1e6f-47ab-8513-3e7816c73dee.jpg",
87 + "reservePriceSet": false,
88 + "biddingStartTime": null
89 + },
90 + {
91 + "id": 106425009,
92 + "title": "Richard - Automatic “Bumper” – Cal. AS 1398 – 40-Micron Gold-Plated - No reserve price - Unisex - 1950-1959 ",
93 + "subtitle": "Automatic - Gold-plated",
94 + "url": "https://www.catawiki.com/en/l/106425009-richard-automatic-bumper-cal-as-1398-40-micron-gold-plated-no-reserve-price-unisex-1950-1959",
95 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/27/e/a/8/ea8e3dfb-48df-451a-81bb-fe7929b5d70c.jpg",
96 + "reservePriceSet": false,
97 + "biddingStartTime": null
98 + },
99 + {
100 + "id": 106433154,
101 + "title": "Rado - Purple Horse - No reserve price - 636.3476.4 - Men - 1970-1979 ",
102 + "subtitle": "Automatic - Gold/Steel, Stainless steel",
103 + "url": "https://www.catawiki.com/en/l/106433154-rado-purple-horse-no-reserve-price-636-3476-4-men-1970-1979",
104 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/4/d/d/4ddd7350-1ad5-429d-a5ba-71d5d9ba3095.jpg",
105 + "reservePriceSet": false,
106 + "biddingStartTime": null
107 + },
108 + {
109 + "id": 106433667,
110 + "title": "Atlantic - Worldmaster Original - No reserve price - 614/10 - Men - 1950-1959 ",
111 + "subtitle": "Manual winding - Stainless steel",
112 + "url": "https://www.catawiki.com/en/l/106433667-atlantic-worldmaster-original-no-reserve-price-614-10-men-1950-1959",
113 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/0/3/3/033ada34-13f9-480d-bda4-59f9336d804f.jpg",
114 + "reservePriceSet": false,
115 + "biddingStartTime": null
116 + },
117 + {
118 + "id": 106431856,
119 + "title": "J. Chevalier - Swiss - Mechanical - mens - gold plated - Dress Watch – 1970s - No reserve price - Men - 1970-1979 ",
120 + "subtitle": "Manual winding - Gold-plated",
121 + "url": "https://www.catawiki.com/en/l/106431856-j-chevalier-swiss-mechanical-mens-gold-plated-dress-watch-1970s-no-reserve-price-men-1970-1979",
122 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/8/1/c/81cf5a9c-946f-4c81-b1f5-c696bad3de1a.jpg",
123 + "reservePriceSet": false,
124 + "biddingStartTime": null
125 + },
126 + {
127 + "id": 106425076,
128 + "title": "Mondia - orbitron red automatic vintage swiss made - No reserve price - 97-1003-20 - Unisex - 1960-1969 ",
129 + "subtitle": "Automatic - Steel, Gold-plated",
130 + "url": "https://www.catawiki.com/en/l/106425076-mondia-orbitron-red-automatic-vintage-swiss-made-no-reserve-price-97-1003-20-unisex-1960-1969",
131 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/27/d/9/c/d9cce048-e4bc-43ac-af66-90dcb87af078.jpg",
132 + "reservePriceSet": false,
133 + "biddingStartTime": null
134 + },
135 + {
136 + "id": 106431599,
137 + "title": "Juwel Genéve - Swiss - NOS - unused - Mechanical - mens - gold plated - Dress Watch – 1960s - No reserve price - Men - 1960-1969 ",
138 + "subtitle": "Manual winding - Gold-plated",
139 + "url": "https://www.catawiki.com/en/l/106431599-juwel-geneve-swiss-nos-unused-mechanical-mens-gold-plated-dress-watch-1960s-no-reserve-price-men-1960-1969",
140 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/d/b/6/db62eae6-d612-49af-95c2-93140b6f5751.jpg",
141 + "reservePriceSet": false,
142 + "biddingStartTime": null
143 + },
144 + {
145 + "id": 106430055,
146 + "title": "Silvana - Military Design - No reserve price - Men - 1950-1959 ",
147 + "subtitle": "Manual winding - Gold-plated",
148 + "url": "https://www.catawiki.com/en/l/106430055-silvana-military-design-no-reserve-price-men-1950-1959",
149 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/2/1/a/21a2adc9-e2e4-43b1-a94f-5aef9c028d4f.jpg",
150 + "reservePriceSet": false,
151 + "biddingStartTime": null
152 + },
153 + {
154 + "id": 106425191,
155 + "title": "Moulinet - Mechanical - Cal. AS 1187 – Stainless Steel - Concentric guilloché dial - No reserve price - Unisex - 1900-1949 ",
156 + "subtitle": "Manual winding - Stainless steel",
157 + "url": "https://www.catawiki.com/en/l/106425191-moulinet-mechanical-cal-as-1187-stainless-steel-concentric-guilloche-dial-no-reserve-price-unisex-1900-1949",
158 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/27/0/4/e/04e00a7b-127c-42f7-a8d2-1ae1cf386d03.jpg",
159 + "reservePriceSet": false,
160 + "biddingStartTime": null
161 + },
162 + {
163 + "id": 106425021,
164 + "title": "Silvana - 60 Skin Diver Black Dial 38mm Steel 20 Atm Sub - No reserve price - Unisex - 1960-1969 ",
165 + "subtitle": "Automatic - Steel",
166 + "url": "https://www.catawiki.com/en/l/106425021-silvana-60-skin-diver-black-dial-38mm-steel-20-atm-sub-no-reserve-price-unisex-1960-1969",
167 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/27/5/e/c/5ec3466b-8874-4210-856f-301b5d1edbb7.jpg",
168 + "reservePriceSet": false,
169 + "biddingStartTime": null
170 + },
171 + {
172 + "id": 106429906,
173 + "title": "Tissot - Carrousel - No reserve price - Men - 1970-1979 ",
174 + "subtitle": "Manual winding - Gold-plated",
175 + "url": "https://www.catawiki.com/en/l/106429906-tissot-carrousel-no-reserve-price-men-1970-1979",
176 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/9/e/e/9eeaa851-b200-44aa-a9bb-b47f268c135b.jpg",
177 + "reservePriceSet": false,
178 + "biddingStartTime": null
179 + },
180 + {
181 + "id": 106432218,
182 + "title": "Saintis - France - Mechanical - mens - gold plated - Dress Watch – 1970s - No reserve price - Men - 1970-1979 ",
183 + "subtitle": "Manual winding - Gold-plated",
184 + "url": "https://www.catawiki.com/en/l/106432218-saintis-france-mechanical-mens-gold-plated-dress-watch-1970s-no-reserve-price-men-1970-1979",
185 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/0/2/d/02dfb7bd-a8a6-4471-9e99-50110aa72525.jpg",
186 + "reservePriceSet": false,
187 + "biddingStartTime": null
188 + },
189 + {
190 + "id": 106429645,
191 + "title": "Nisus - Jubilé - No reserve price - Men - 1950-1959 ",
192 + "subtitle": "Manual winding - Gold-plated",
193 + "url": "https://www.catawiki.com/en/l/106429645-nisus-jubile-no-reserve-price-men-1950-1959",
194 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/3/b/9/3b9f5a21-421d-494e-9996-1437834b42fc.jpg",
195 + "reservePriceSet": false,
196 + "biddingStartTime": null
197 + },
198 + {
199 + "id": 106431309,
200 + "title": "Rado - Golden Horse - No reserve price - 623 3001 4 - Men - 1970-1979 ",
201 + "subtitle": "Automatic - Stainless steel",
202 + "url": "https://www.catawiki.com/en/l/106431309-rado-golden-horse-no-reserve-price-623-3001-4-men-1970-1979",
203 + "imageUrl": "https://assets.catawiki.nl/assets/2026/7/29/2/2/b/22b2fd35-6323-433c-8dfe-5bcd6642d8a0.jpg",
204 + "reservePriceSet": false,
205 + "biddingStartTime": null
206 + },
207 + {
208 + "id": 106429752,
209 + "title": "Stenis Calatrava - Small Second - No reserve price - Men - 1960-1969 ",
210 + "subtitle": "Manual winding - Stainless steel",
211 + "url": "https://www.catawiki.com/en/l/106429752-stenis-calatrava-small-second-no-reserve-price-men-1960-1969",
212 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/c/5/6/c56a0f92-a46d-4064-adf3-559089677dfe.jpg",
213 + "reservePriceSet": false,
214 + "biddingStartTime": null
215 + },
216 + {
217 + "id": 106432131,
218 + "title": "Bulova - No reserve price - 3784181 - Men - 1974",
219 + "subtitle": "Other - Gold-plated",
220 + "url": "https://www.catawiki.com/en/l/106432131-bulova-no-reserve-price-3784181-men-1974",
221 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/3/5/f/35f93330-d3ff-4cb4-bb4d-d4ec7c338a30.jpg",
222 + "reservePriceSet": false,
223 + "biddingStartTime": null
224 + },
225 + {
226 + "id": 106431815,
227 + "title": "Citizen - Seven Star - No reserve price - APSS 2803-Y - Men - 1960-1969 ",
228 + "subtitle": "Automatic - Stainless steel",
229 + "url": "https://www.catawiki.com/en/l/106431815-citizen-seven-star-no-reserve-price-apss-2803-y-men-1960-1969",
230 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/5/1/0/5100439b-91d4-4348-badf-d550e5f93519.jpg",
231 + "reservePriceSet": false,
232 + "biddingStartTime": null
233 + },
234 + {
235 + "id": 106440038,
236 + "title": "horus - diver vintage swiss made automatic steel 10atm - No reserve price - Unisex - 1970-1979 ",
237 + "subtitle": "Automatic - Steel",
238 + "url": "https://www.catawiki.com/en/l/106440038-horus-diver-vintage-swiss-made-automatic-steel-10atm-no-reserve-price-unisex-1970-1979",
239 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/1/b/7/1b7542bc-bfb9-45c5-955d-da5f187a123d.jpg",
240 + "reservePriceSet": false,
241 + "biddingStartTime": null
242 + },
243 + {
244 + "id": 106434995,
245 + "title": "Pryngeps - special - No reserve price - Men - 1960-1969 ",
246 + "subtitle": "Automatic - golden",
247 + "url": "https://www.catawiki.com/en/l/106434995-pryngeps-special-no-reserve-price-men-1960-1969",
248 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/9/9/5/9955f822-69d2-42f1-8641-60b804e87342.jpg",
249 + "reservePriceSet": false,
250 + "biddingStartTime": null
251 + },
252 + {
253 + "id": 106444844,
254 + "title": "Pryngeps - restige swiss made vintage gold plated - No reserve price - Unisex - 1970-1979 ",
255 + "subtitle": "Manual winding - Steel, Gold-plated",
256 + "url": "https://www.catawiki.com/en/l/106444844-pryngeps-restige-swiss-made-vintage-gold-plated-no-reserve-price-unisex-1970-1979",
257 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/27/b/d/4/bd4347ec-2c16-4303-a484-f7a8fa9c0839.jpg",
258 + "reservePriceSet": false,
259 + "biddingStartTime": null
260 + },
261 + {
262 + "id": 106397315,
263 + "title": "Certina - Ref 5206 148 - No reserve price - Men - 1971",
264 + "subtitle": "Manual winding - Gold-plated",
265 + "url": "https://www.catawiki.com/en/l/106397315-certina-ref-5206-148-no-reserve-price-men-1971",
266 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/26/2/8/8/28837709-a64f-49b0-ab97-9f847e9055fe.jpg",
267 + "reservePriceSet": false,
268 + "biddingStartTime": null
269 + },
270 + {
271 + "id": 106442428,
272 + "title": "Lip - Vintage - No reserve price - 542563 - Unisex - 1950-1959 ",
273 + "subtitle": "Manual winding - Gold-plated, Stainless steel",
274 + "url": "https://www.catawiki.com/en/l/106442428-lip-vintage-no-reserve-price-542563-unisex-1950-1959",
275 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/6/1/3/61363042-4db8-4a82-97b0-76a78bdd0686.jpg",
276 + "reservePriceSet": false,
277 + "biddingStartTime": null
278 + },
279 + {
280 + "id": 106444923,
281 + "title": "capri - racing team swiss made NOS model deposè - No reserve price - Unisex - 1970-1979 ",
282 + "subtitle": "Manual winding - Bakelite",
283 + "url": "https://www.catawiki.com/en/l/106444923-capri-racing-team-swiss-made-nos-model-depose-no-reserve-price-unisex-1970-1979",
284 + "imageUrl": "https://assets.catawiki.nl/assets/2025/12/16/7/5/a/75abfd38-687a-4f71-9a4f-dacfee9a2b44.jpg",
285 + "reservePriceSet": false,
286 + "biddingStartTime": null
287 + },
288 + {
289 + "id": 106443145,
290 + "title": "Alpina - Tresor – Cal. 762 - No reserve price - Men - 1930",
291 + "subtitle": "Manual winding - Stainless steel",
292 + "url": "https://www.catawiki.com/en/l/106443145-alpina-tresor-cal-762-no-reserve-price-men-1930",
293 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/4/d/c/4dcedda8-08de-4167-bef7-577a4c61eed8.jpg",
294 + "reservePriceSet": false,
295 + "biddingStartTime": null
296 + },
297 + {
298 + "id": 106363526,
299 + "title": "Louvic DeLux-Mistery Dial Diamonds,Vintage'60. - No reserve price - Women - 1960-1969 ",
300 + "subtitle": "Manual winding - Steel, Chrome-plated steel",
301 + "url": "https://www.catawiki.com/en/l/106363526-louvic-delux-mistery-dial-diamonds-vintage-60-no-reserve-price-women-1960-1969",
302 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/27/f/e/6/fe620622-eba3-4aa1-b4ca-1d7c5d8f81ce.jpg",
303 + "reservePriceSet": false,
304 + "biddingStartTime": null
305 + },
306 + {
307 + "id": 106434347,
308 + "title": "Roamer - No reserve price - 5907 - Men - 1950-1959 ",
309 + "subtitle": "Manual winding - Gold-plated, Stainless steel",
310 + "url": "https://www.catawiki.com/en/l/106434347-roamer-no-reserve-price-5907-men-1950-1959",
311 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/5/f/4/5f4b0cbd-9438-424a-afa5-668d38cf60bb.jpg",
312 + "reservePriceSet": false,
313 + "biddingStartTime": null
314 + },
315 + {
316 + "id": 106437054,
317 + "title": "Junghans - Cal 687 vor Max Bill Era - No reserve price - Men - 1960-1969 ",
318 + "subtitle": "Manual winding - Steel",
319 + "url": "https://www.catawiki.com/en/l/106437054-junghans-cal-687-vor-max-bill-era-no-reserve-price-men-1960-1969",
320 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/c/5/3/c530b6a9-ac68-4b0b-ba6f-5d9657e99bbf.jpg",
321 + "reservePriceSet": false,
322 + "biddingStartTime": null
323 + },
324 + {
325 + "id": 106438848,
326 + "title": "Stowa - Parat - No reserve price - Art Déco \"Tank\" Black Dial - Kal. Osco 42 - Men - 1900-1949 ",
327 + "subtitle": "Manual winding - Gold-plated",
328 + "url": "https://www.catawiki.com/en/l/106438848-stowa-parat-no-reserve-price-art-deco-tank-black-dial-kal-osco-42-men-1900-1949",
329 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/8/4/b/84bd1018-0218-4193-b428-ae6569334470.jpg",
330 + "reservePriceSet": false,
331 + "biddingStartTime": null
332 + },
333 + {
334 + "id": 106441082,
335 + "title": "kirovskie - k43 - No reserve price - Men - 1900-1949 ",
336 + "subtitle": "Manual winding - Steel",
337 + "url": "https://www.catawiki.com/en/l/106441082-kirovskie-k43-no-reserve-price-men-1900-1949",
338 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/8/4/0/840d51f3-21ef-4434-bb48-7c00e467785a.jpg",
339 + "reservePriceSet": false,
340 + "biddingStartTime": null
341 + },
342 + {
343 + "id": 106442847,
344 + "title": "Aero-Matic - No reserve price - 732 698205 - Men - 1965",
345 + "subtitle": "Automatic - Stainless steel",
346 + "url": "https://www.catawiki.com/en/l/106442847-aero-matic-no-reserve-price-732-698205-men-1965",
347 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/7/1/0/7107d5ee-0f48-42fc-a693-bd3e473244a8.jpg",
348 + "reservePriceSet": false,
349 + "biddingStartTime": null
350 + },
351 + {
352 + "id": 106423037,
353 + "title": "Certina - Waterking - No reserve price - 25-66 - Unisex - 1960",
354 + "subtitle": "Manual winding - Gold-plated",
355 + "url": "https://www.catawiki.com/en/l/106423037-certina-waterking-no-reserve-price-25-66-unisex-1960",
356 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/27/4/9/1/491c4cd7-7e8d-442d-ab83-97e2f2beaa10.jpg",
357 + "reservePriceSet": false,
358 + "biddingStartTime": null
359 + },
360 + {
361 + "id": 106430124,
362 + "title": "Rodos - No reserve price - 5145 RG - Men - 1960-1969 ",
363 + "subtitle": "Manual winding - Gold-plated, Stainless steel",
364 + "url": "https://www.catawiki.com/en/l/106430124-rodos-no-reserve-price-5145-rg-men-1960-1969",
365 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/9/b/b/9bb69e0e-3d77-4535-94cc-a3f568e50689.jpg",
366 + "reservePriceSet": false,
367 + "biddingStartTime": null
368 + },
369 + {
370 + "id": 106439475,
371 + "title": "Baume & Mercier - Vintage Genève Ultra-Slim Dress Watch - Men - 1960-1969 ",
372 + "subtitle": "Manual winding - Stainless steel",
373 + "url": "https://www.catawiki.com/en/l/106439475-baume-mercier-vintage-geneve-ultra-slim-dress-watch-men-1960-1969",
374 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/6/c/4/5/c45f376f-5ab2-434f-a86e-161caaec878f.jpg",
375 + "reservePriceSet": true,
376 + "biddingStartTime": null
377 + },
378 + {
379 + "id": 106118127,
380 + "title": "IWC - R810A - Unisex - 1960-1969 ",
381 + "subtitle": "Automatic - Steel, Stainless steel",
382 + "url": "https://www.catawiki.com/en/l/106118127-iwc-r810a-unisex-1960-1969",
383 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/15/0/4/c/04c434b7-3880-461d-acdb-71614b83a0b6.jpg",
384 + "reservePriceSet": true,
385 + "biddingStartTime": null
386 + },
387 + {
388 + "id": 106435355,
389 + "title": "Cauny - prima - No reserve price - 192 757 - Men - 1950-1959 ",
390 + "subtitle": "Manual winding - Stainless steel",
391 + "url": "https://www.catawiki.com/en/l/106435355-cauny-prima-no-reserve-price-192-757-men-1950-1959",
392 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/8/8/e/88e29b9a-d8f1-45bf-914d-8cf354b0c50a.jpg",
393 + "reservePriceSet": false,
394 + "biddingStartTime": null
395 + },
396 + {
397 + "id": 106438115,
398 + "title": "Citizen - Vintage - No reserve price - 4-520075 Y - Men - 1970-1979 ",
399 + "subtitle": "Automatic - Stainless steel",
400 + "url": "https://www.catawiki.com/en/l/106438115-citizen-vintage-no-reserve-price-4-520075-y-men-1970-1979",
401 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/a/9/c/a9c1d2d7-cfde-4537-8372-f2dae4ce576b.jpg",
402 + "reservePriceSet": false,
403 + "biddingStartTime": null
404 + },
405 + {
406 + "id": 106436212,
407 + "title": "Caravelle ( Bulova ) Swiss - Classic Skeleton 21Rubis - No reserve price - N-8 - Men - 1970-1979 ",
408 + "subtitle": "Manual winding - Stainless steel, Metal, Gold-plated",
409 + "url": "https://www.catawiki.com/en/l/106436212-caravelle-bulova-swiss-classic-skeleton-21rubis-no-reserve-price-n-8-men-1970-1979",
410 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/f/f/1/ff1cfcac-a2dd-4846-860a-57c781b63b3f.jpg",
411 + "reservePriceSet": false,
412 + "biddingStartTime": null
413 + },
414 + {
415 + "id": 106438180,
416 + "title": "Citizen - Seven Star Deluxe - No reserve price - Men - 1970-1979 ",
417 + "subtitle": "Automatic - Stainless steel",
418 + "url": "https://www.catawiki.com/en/l/106438180-citizen-seven-star-deluxe-no-reserve-price-men-1970-1979",
419 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/e/d/e/ede13b96-18ff-4758-ad10-aab08ad95a1a.jpg",
420 + "reservePriceSet": false,
421 + "biddingStartTime": null
422 + },
423 + {
424 + "id": 106437184,
425 + "title": "Koha ( Hans Kohnen ) - Classic Calendar 17Rubis - No reserve price - 6821 - Men - 1960-1969 ",
426 + "subtitle": "Manual winding - Stainless steel, Metal, Gold-plated",
427 + "url": "https://www.catawiki.com/en/l/106437184-koha-hans-kohnen-classic-calendar-17rubis-no-reserve-price-6821-men-1960-1969",
428 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/7/8/c/78c3fc1c-55ef-4406-85ea-ee98e6688b5d.jpg",
429 + "reservePriceSet": false,
430 + "biddingStartTime": null
431 + },
432 + {
433 + "id": 106283105,
434 + "title": "Sicura (Breitling) - Day-Date Automatic - No reserve price - Men - 1975",
435 + "subtitle": "Automatic - Steel, Gold-plated",
436 + "url": "https://www.catawiki.com/en/l/106283105-sicura-breitling-day-date-automatic-no-reserve-price-men-1975",
437 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/7/f/5/7f5e7d6a-f7ca-4c6d-bf41-972e31ad704f.jpg",
438 + "reservePriceSet": false,
439 + "biddingStartTime": null
440 + },
441 + {
442 + "id": 106325270,
443 + "title": "Diehl Junghans - Compact - No reserve price - Men - 1970",
444 + "subtitle": "Manual winding - Gold-plated",
445 + "url": "https://www.catawiki.com/en/l/106325270-diehl-junghans-compact-no-reserve-price-men-1970",
446 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/a/8/e/a8e4b6a1-8295-4847-86ec-b2883c37bf82.jpg",
447 + "reservePriceSet": false,
448 + "biddingStartTime": null
449 + },
450 + {
451 + "id": 106445380,
452 + "title": "Glashütte Spezimatic - cal. 75 - No reserve price - Men - 1980-1989 ",
453 + "subtitle": "Automatic - Steel",
454 + "url": "https://www.catawiki.com/en/l/106445380-glashutte-spezimatic-cal-75-no-reserve-price-men-1980-1989",
455 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/c/3/4/c3460011-f640-40f8-87a9-b021848602bf.jpg",
456 + "reservePriceSet": false,
457 + "biddingStartTime": null
458 + },
459 + {
460 + "id": 106445129,
461 + "title": "Festa - Alpina Cal. 843 / Venus 130 - No reserve price - Men - 1930",
462 + "subtitle": "Manual winding - Stainless steel, Gold-plated",
463 + "url": "https://www.catawiki.com/en/l/106445129-festa-alpina-cal-843-venus-130-no-reserve-price-men-1930",
464 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/d/2/b/d2b936df-24cc-430e-83de-f8660098ceb2.jpg",
465 + "reservePriceSet": false,
466 + "biddingStartTime": null
467 + },
468 + {
469 + "id": 106446881,
470 + "title": "StopWatch Tip - Chonostop - No reserve price - Men - 1950-1959 ",
471 + "subtitle": "Manual winding - Gold-plated",
472 + "url": "https://www.catawiki.com/en/l/106446881-stopwatch-tip-chonostop-no-reserve-price-men-1950-1959",
473 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/b/9/3/b93974c9-31a0-4e60-88cd-807513850983.jpg",
474 + "reservePriceSet": false,
475 + "biddingStartTime": null
476 + },
477 + {
478 + "id": 105875599,
479 + "title": "Lusina Geneve Pointerdate - Genève - No reserve price - 114050 - Men - 1948",
480 + "subtitle": "Manual winding - Gold-plated",
481 + "url": "https://www.catawiki.com/en/l/105875599-lusina-geneve-pointerdate-geneve-no-reserve-price-114050-men-1948",
482 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/4/c/7/4/c74ed459-fee3-447b-b0f4-0b1eee87df73.jpg",
483 + "reservePriceSet": false,
484 + "biddingStartTime": null
485 + },
486 + {
487 + "id": 106339788,
488 + "title": "Universal Genève - No reserve price - Cal. 1-42 Ref. 542109 - Men - 1970-1979 ",
489 + "subtitle": "Manual winding - Stainless steel",
490 + "url": "https://www.catawiki.com/en/l/106339788-universal-geneve-no-reserve-price-cal-1-42-ref-542109-men-1970-1979",
491 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/9/8/3/98341c59-bf47-47ee-b99b-bdd3e6fe62ab.jpg",
492 + "reservePriceSet": false,
493 + "biddingStartTime": null
494 + },
495 + {
496 + "id": 106448764,
497 + "title": "Certina - Sub-second | Cal. 320 - No reserve price - 81101 - Men - 1954",
498 + "subtitle": "Manual winding - Stainless steel",
499 + "url": "https://www.catawiki.com/en/l/106448764-certina-sub-second-cal-320-no-reserve-price-81101-men-1954",
500 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/7/9/3/79312041-6fc5-42bf-974e-c91ad3d3531a.jpg",
501 + "reservePriceSet": false,
502 + "biddingStartTime": null
503 + },
504 + {
505 + "id": 106385554,
506 + "title": "Richard Geneve - Automatic - No reserve price - Men - 1970-1979 ",
507 + "subtitle": "Automatic - Steel",
508 + "url": "https://www.catawiki.com/en/l/106385554-richard-geneve-automatic-no-reserve-price-men-1970-1979",
509 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/26/3/b/b/3bbf80d2-13d2-4b0f-a7a1-a0e444bf65b3.jpg",
510 + "reservePriceSet": false,
511 + "biddingStartTime": null
512 + },
513 + {
514 + "id": 106450800,
515 + "title": "Rado - Companion III - No reserve price - 12122 - Men - 1970-1979 ",
516 + "subtitle": "Automatic - Stainless steel",
517 + "url": "https://www.catawiki.com/en/l/106450800-rado-companion-iii-no-reserve-price-12122-men-1970-1979",
518 + "imageUrl": "https://assets.catawiki.nl/assets/2026/6/26/c/b/3/cb3824d8-0349-4a54-a4cd-594e46820bb3.jpg",
519 + "reservePriceSet": false,
520 + "biddingStartTime": null
521 + },
522 + {
523 + "id": 106450804,
524 + "title": "Junghans - Trilastic - No reserve price - Men - 1950-1959 ",
525 + "subtitle": "Manual winding - Gold-plated",
526 + "url": "https://www.catawiki.com/en/l/106450804-junghans-trilastic-no-reserve-price-men-1950-1959",
527 + "imageUrl": "https://assets.catawiki.nl/assets/2026/7/23/6/1/7/617f3bc8-76d6-4f2a-b410-844bc599694f.jpg",
528 + "reservePriceSet": false,
529 + "biddingStartTime": null
530 + },
531 + {
532 + "id": 106450806,
533 + "title": "Bulova - Squadron - No reserve price - 6828659 - Men - 1943",
534 + "subtitle": "Manual winding - Gold-plated",
535 + "url": "https://www.catawiki.com/en/l/106450806-bulova-squadron-no-reserve-price-6828659-men-1943",
536 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/8/f/3/c/f3cf563f-8e6b-44e4-a82b-94fb43b460f5.jpg",
537 + "reservePriceSet": false,
538 + "biddingStartTime": null
539 + },
540 + {
541 + "id": 106450961,
542 + "title": "Rado - Lepordeluxe - No reserve price - N0650538 - Women - 1970-1979 ",
543 + "subtitle": "Manual winding - Silver",
544 + "url": "https://www.catawiki.com/en/l/106450961-rado-lepordeluxe-no-reserve-price-n0650538-women-1970-1979",
545 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/13/5/d/f/5df404df-4d7a-4b32-9ef4-7fc58bebadfd.jpg",
546 + "reservePriceSet": false,
547 + "biddingStartTime": null
548 + },
549 + {
550 + "id": 106448949,
551 + "title": "Certina - Certina Revelation Automatic + Crystal Tool - No reserve price - 8308170 - Unisex - 1971",
552 + "subtitle": "Automatic - Stainless steel",
553 + "url": "https://www.catawiki.com/en/l/106448949-certina-certina-revelation-automatic-crystal-tool-no-reserve-price-8308170-unisex-1971",
554 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/1/b/c/1bcd32ff-dfc4-44f1-8574-5ac1fa616d92.jpg",
555 + "reservePriceSet": false,
556 + "biddingStartTime": null
557 + },
558 + {
559 + "id": 106452821,
560 + "title": "Citizen - ADOREX Automatic Hi-Beat 1970-1979 Men",
561 + "subtitle": "Worn & in very good condition",
562 + "url": "https://www.catawiki.com/en/l/106452821-citizen-adorex-automatic-hi-beat-1970-1979-men",
563 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/28/c/3/d/c3d1dafd-d906-4404-a4b3-b07eace42f6b.jpg",
564 + "reservePriceSet": false,
565 + "biddingStartTime": null
566 + },
567 + {
568 + "id": 106456952,
569 + "title": "Phigied - oro giallo 18 carati - Women - 1900-1949 ",
570 + "subtitle": "Manual winding - Yellow gold",
571 + "url": "https://www.catawiki.com/en/l/106456952-phigied-oro-giallo-18-carati-women-1900-1949",
572 + "imageUrl": "https://assets.catawiki.nl/assets/2026/7/11/a/e/e/aee8b0a7-bad9-49e2-bb62-d71d8258b0c1.jpg",
573 + "reservePriceSet": true,
574 + "biddingStartTime": null
575 + },
576 + {
577 + "id": 106459197,
578 + "title": "Nacar - AS 1130 / 17 Jewels – Manual Wind – Textured Dial - No reserve price - Men - 1950-1959 ",
579 + "subtitle": "Manual winding - Gold-plated",
580 + "url": "https://www.catawiki.com/en/l/106459197-nacar-as-1130-17-jewels-manual-wind-textured-dial-no-reserve-price-men-1950-1959",
581 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/29/e/1/b/e1b2df91-6b67-416e-94ec-ca8d5747c820.jpg",
582 + "reservePriceSet": false,
583 + "biddingStartTime": null
584 + },
585 + {
586 + "id": 106459697,
587 + "title": "Nacar - Auto Dater Rookie “Jet” – 17 Jewels – Para Water – Vintage - No reserve price - Men - 1960-1969 ",
588 + "subtitle": "Automatic - Gold-plated",
589 + "url": "https://www.catawiki.com/en/l/106459697-nacar-auto-dater-rookie-jet-17-jewels-para-water-vintage-no-reserve-price-men-1960-1969",
590 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/29/8/1/b/81b95f7f-0fc9-42c5-b10f-865677f18d09.jpg",
591 + "reservePriceSet": false,
592 + "biddingStartTime": null
593 + },
594 + {
595 + "id": 106456147,
596 + "title": "Mortima - Mayerling - vintage classic France - 17 Jewels - No reserve price - Men - 1970",
597 + "subtitle": "Manual winding - Chromed",
598 + "url": "https://www.catawiki.com/en/l/106456147-mortima-mayerling-vintage-classic-france-17-jewels-no-reserve-price-men-1970",
599 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/29/7/5/3/7534c060-e671-477a-ba5e-821770713727.jpg",
600 + "reservePriceSet": false,
601 + "biddingStartTime": null
602 + },
603 + {
604 + "id": 106453982,
605 + "title": "Yema - Sous - Marine - vintage diver France - 330 Feet - No reserve price - Men - 1960",
606 + "subtitle": "Manual winding - Steel",
607 + "url": "https://www.catawiki.com/en/l/106453982-yema-sous-marine-vintage-diver-france-330-feet-no-reserve-price-men-1960",
608 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/29/7/8/d/78d9fb99-6c3e-4722-9801-cb7167fd489a.jpg",
609 + "reservePriceSet": false,
610 + "biddingStartTime": null
611 + },
612 + {
613 + "id": 106467638,
614 + "title": "Maty - MATY Besancon Calendar – Vintage Manual-Wind Triple Calendar – 17 Jewels - No reserve price - Men - 1970",
615 + "subtitle": "Manual winding - Gold-plated",
616 + "url": "https://www.catawiki.com/en/l/106467638-maty-maty-besancon-calendar-vintage-manual-wind-triple-calendar-17-jewels-no-reserve-price-men-1970",
617 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/30/0/f/d/0fd5b397-984a-4aba-8056-a75ba6fe54a0.jpg",
618 + "reservePriceSet": false,
619 + "biddingStartTime": null
620 + },
621 + {
622 + "id": 106469806,
623 + "title": "Vetta - Automatic Date - Oversize - Cal.472 - No reserve price - Ref.10282 - Men - 1970-1979 ",
624 + "subtitle": "Automatic - Gold-plated",
625 + "url": "https://www.catawiki.com/en/l/106469806-vetta-automatic-date-oversize-cal-472-no-reserve-price-ref-10282-men-1970-1979",
626 + "imageUrl": "https://assets.catawiki.nl/assets/2026/5/10/8/8/4/884bdf6a-e178-4834-a22f-5636c7dac9c7.jpg",
627 + "reservePriceSet": false,
628 + "biddingStartTime": null
629 + },
630 + {
631 + "id": 106468243,
632 + "title": "Rado - DiaStar - No reserve price - Men - 1970-1979 ",
633 + "subtitle": "Automatic - Gold-plated",
634 + "url": "https://www.catawiki.com/en/l/106468243-rado-diastar-no-reserve-price-men-1970-1979",
635 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/30/8/7/4/874a40e9-e23c-454b-b9b4-9135c34979f1.jpg",
636 + "reservePriceSet": false,
637 + "biddingStartTime": null
638 + },
639 + {
640 + "id": 106471016,
641 + "title": "Incalblock - Antimagnetique - No reserve price - Men - 1950",
642 + "subtitle": "Manual winding - Gold-plated",
643 + "url": "https://www.catawiki.com/en/l/106471016-incalblock-antimagnetique-no-reserve-price-men-1950",
644 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/30/3/8/0/3805d386-67a2-434c-b414-c8d490f28c72.jpg",
645 + "reservePriceSet": false,
646 + "biddingStartTime": null
647 + },
648 + {
649 + "id": 106468239,
650 + "title": "Oris - Big Crown Pointer Date - No reserve price - Cal 704 Military Swiss Watch - Men - 1950-1959 ",
651 + "subtitle": "Manual winding - Stainless steel",
652 + "url": "https://www.catawiki.com/en/l/106468239-oris-big-crown-pointer-date-no-reserve-price-cal-704-military-swiss-watch-men-1950-1959",
653 + "imageUrl": "https://assets.catawiki.nl/assets/2026/8/30/1/6/4/164738a3-4683-411b-8eb1-ce2e24b63680.jpg",
654 + "reservePriceSet": false,
655 + "biddingStartTime": null
656 + }
657 + ]
658 + },
659 + "fetchedAt": "2026-09-07T06:02:44.097Z"
660 + },
661 + "expect": {
662 + "minCount": 1,
663 + "kinds": [
664 + "auction_lot"
665 + ],
666 + "first": {
667 + "kind": "auction_lot",
668 + "auctionHouse": "Catawiki",
669 + "currency": "EUR"
670 + }
671 + },
672 + "note": "Captured live by connectors/api/_auction-lib/smoke.ts on 2026-09-07 (70 records from this raw page).",
673 + "capturedAt": "2026-09-07T06:02:44.106Z"
674 +}
\ No newline at end of file
added data/fixtures/christies/results-1.json +1432 −0
@@ -0,0 +1,1432 @@
1 +{
2 + "raw": {
3 + "url": "https://www.christies.com/api/discoverywebsite/auctionpages/lotsearch?language=en&SaleNumber=24637&SaleId=31276&page=1&pageSize=20&sortby=lotnumber",
4 + "externalId": "24637#1",
5 + "kind": "sale",
6 + "engine": "api",
7 + "httpStatus": 200,
8 + "payload": {
9 + "kind": "sale_lots",
10 + "sale": {
11 + "saleId": "31276",
12 + "saleNumber": "24637",
13 + "title": "Studio 1766: Christie's London Staff Art Show",
14 + "subtitle": "Online Auction 24637 | CLOSED",
15 + "eventType": "Online",
16 + "location": "London",
17 + "startDate": "2026-08-20T00:00:00",
18 + "endDate": "2026-09-03T00:00:00",
19 + "landingUrl": "https://onlineonly.christies.com/sso?SaleID=31276&SaleNumber=24637",
20 + "categoryLabels": [
21 + "Fine Art"
22 + ],
23 + "saleTotalText": "GBP 16,637"
24 + },
25 + "page": 1,
26 + "totalHits": 73,
27 + "lots": [
28 + {
29 + "objectId": "6598241",
30 + "lotNumber": "1",
31 + "titlePrimary": "UMIT ZEYTINCIOGLU",
32 + "titleSecondary": "City of Villages, Revisited, 2025",
33 + "titleTertiary": null,
34 + "description": "UMIT ZEYTINCIOGLU City of Villages, Revisited, 2025 photographic print on aluminium 20 cm. high x 25 cm. wide",
35 + "url": "https://www.christies.com/en/sso?ObjectID=24637.1&LotNumber=1&ldp_breadcrumb=back",
36 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0001_000(umit_zeytincioglu_city_of_villages_revisited_2025054107).jpg?mode=max",
37 + "estimateLow": 100,
38 + "estimateHigh": 200,
39 + "estimateText": "GBP 100 - 200",
40 + "priceRealised": null,
41 + "priceRealisedText": null,
42 + "startDate": "2026-08-20T00:00Z",
43 + "endDate": "2026-09-02T23:00Z",
44 + "withdrawn": false,
45 + "isOver": true
46 + },
47 + {
48 + "objectId": "6598242",
49 + "lotNumber": "2",
50 + "titlePrimary": "UMIT ZEYTINCIOGLU",
51 + "titleSecondary": "Impetious, 2024",
52 + "titleTertiary": null,
53 + "description": "UMIT ZEYTINCIOGLU Impetious, 2024 photographic print, semi matte paper framed: 31.5 cm. high x 41.5 cm. wide",
54 + "url": "https://www.christies.com/en/sso?ObjectID=24637.2&LotNumber=2&ldp_breadcrumb=back",
55 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0002_000(umit_zeytincioglu_impetious_2024054119).jpg?mode=max",
56 + "estimateLow": 100,
57 + "estimateHigh": 200,
58 + "estimateText": "GBP 100 - 200",
59 + "priceRealised": 127,
60 + "priceRealisedText": "GBP 127",
61 + "startDate": "2026-08-20T00:00Z",
62 + "endDate": "2026-09-02T23:00Z",
63 + "withdrawn": false,
64 + "isOver": true
65 + },
66 + {
67 + "objectId": "6598243",
68 + "lotNumber": "3",
69 + "titlePrimary": "UMIT ZEYTINCIOGLU",
70 + "titleSecondary": "Look About You, 2025",
71 + "titleTertiary": null,
72 + "description": "UMIT ZEYTINCIOGLU Look About You, 2025 photographic print, on Fuji Velvet Paper image: 39 cm. high x 30 cm. wide framed: 57 cm. high x 47 cm. wide",
73 + "url": "https://www.christies.com/en/sso?ObjectID=24637.3&LotNumber=3&ldp_breadcrumb=back",
74 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0003_000(umit_zeytincioglu_look_about_you_2025054132).jpg?mode=max",
75 + "estimateLow": 100,
76 + "estimateHigh": 200,
77 + "estimateText": "GBP 100 - 200",
78 + "priceRealised": null,
79 + "priceRealisedText": null,
80 + "startDate": "2026-08-20T00:00Z",
81 + "endDate": "2026-09-02T23:00Z",
82 + "withdrawn": false,
83 + "isOver": true
84 + },
85 + {
86 + "objectId": "6598244",
87 + "lotNumber": "4",
88 + "titlePrimary": "ABIGAIL DEAKIN",
89 + "titleSecondary": "Spur, 2026",
90 + "titleTertiary": null,
91 + "description": "ABIGAIL DEAKIN Spur, 2026 signed 'A.Deakin' (lower right) oil on canvas 50 cm. high x 40 cm. wide",
92 + "url": "https://www.christies.com/en/sso?ObjectID=24637.4&LotNumber=4&ldp_breadcrumb=back",
93 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0004_000(abigail_deakin_spur_2026054138).jpg?mode=max",
94 + "estimateLow": 1500,
95 + "estimateHigh": 2500,
96 + "estimateText": "GBP 1,500 - 2,500",
97 + "priceRealised": null,
98 + "priceRealisedText": null,
99 + "startDate": "2026-08-20T00:00Z",
100 + "endDate": "2026-09-02T23:00Z",
101 + "withdrawn": false,
102 + "isOver": true
103 + },
104 + {
105 + "objectId": "6598245",
106 + "lotNumber": "5",
107 + "titlePrimary": "ABIGAIL DEAKIN",
108 + "titleSecondary": "Passing, 2026",
109 + "titleTertiary": null,
110 + "description": "ABIGAIL DEAKIN Passing, 2026 signed 'A. Deakin' (lower right) oil on canvas 100 cm. high x 70 cm. wide",
111 + "url": "https://www.christies.com/en/sso?ObjectID=24637.5&LotNumber=5&ldp_breadcrumb=back",
112 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0005_000(abigail_deakin_passing_2026054146).jpg?mode=max",
113 + "estimateLow": 3000,
114 + "estimateHigh": 4000,
115 + "estimateText": "GBP 3,000 - 4,000",
116 + "priceRealised": 3048,
117 + "priceRealisedText": "GBP 3,048",
118 + "startDate": "2026-08-20T00:00Z",
119 + "endDate": "2026-09-02T23:00Z",
120 + "withdrawn": false,
121 + "isOver": true
122 + },
123 + {
124 + "objectId": "6598246",
125 + "lotNumber": "6",
126 + "titlePrimary": "ABIGAIL DEAKIN",
127 + "titleSecondary": "Arena, 2026",
128 + "titleTertiary": null,
129 + "description": "ABIGAIL DEAKIN Arena, 2026 signed 'A. Deakin' (lower right) oil on canvas 50 cm. high x 40 cm. wide",
130 + "url": "https://www.christies.com/en/sso?ObjectID=24637.6&LotNumber=6&ldp_breadcrumb=back",
131 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0006_000(abigail_deakin_arena_2026054159).jpg?mode=max",
132 + "estimateLow": 2500,
133 + "estimateHigh": 3500,
134 + "estimateText": "GBP 2,500 - 3,500",
135 + "priceRealised": 2794,
136 + "priceRealisedText": "GBP 2,794",
137 + "startDate": "2026-08-20T00:00Z",
138 + "endDate": "2026-09-02T23:00Z",
139 + "withdrawn": false,
140 + "isOver": true
141 + },
142 + {
143 + "objectId": "6598247",
144 + "lotNumber": "7",
145 + "titlePrimary": "LUZ MARIA OSORIO",
146 + "titleSecondary": "Untitled, 2025",
147 + "titleTertiary": null,
148 + "description": "LUZ MARIA OSORIO Untitled, 2025 signed and dated (on the reverse) archival c-type print, acrylic face mounted framed: 68 cm. high x 101.5 cm. wide",
149 + "url": "https://www.christies.com/en/sso?ObjectID=24637.7&LotNumber=7&ldp_breadcrumb=back",
150 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0007_000(luz_maria_osorio_untitled_2025054205).jpg?mode=max",
151 + "estimateLow": 600,
152 + "estimateHigh": 800,
153 + "estimateText": "GBP 600 - 800",
154 + "priceRealised": null,
155 + "priceRealisedText": null,
156 + "startDate": "2026-08-20T00:00Z",
157 + "endDate": "2026-09-02T23:00Z",
158 + "withdrawn": false,
159 + "isOver": true
160 + },
161 + {
162 + "objectId": "6598248",
163 + "lotNumber": "8",
164 + "titlePrimary": "LUZ MARIA OSORIO",
165 + "titleSecondary": "Untitled, 2023",
166 + "titleTertiary": null,
167 + "description": "LUZ MARIA OSORIO Untitled, 2023 signed and dated (on reverse) archival c-type print, acrylic face mounted framed: 68 cm. high x 101.5 cm. wide",
168 + "url": "https://www.christies.com/en/sso?ObjectID=24637.8&LotNumber=8&ldp_breadcrumb=back",
169 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0008_000(luz_maria_osorio_untitled_2023055041).jpg?mode=max",
170 + "estimateLow": 600,
171 + "estimateHigh": 800,
172 + "estimateText": "GBP 600 - 800",
173 + "priceRealised": null,
174 + "priceRealisedText": null,
175 + "startDate": "2026-08-20T00:00Z",
176 + "endDate": "2026-09-02T23:00Z",
177 + "withdrawn": false,
178 + "isOver": true
179 + },
180 + {
181 + "objectId": "6598249",
182 + "lotNumber": "9",
183 + "titlePrimary": "MARIA FALCO",
184 + "titleSecondary": "Zero Hour Series - Creature, 2025",
185 + "titleTertiary": null,
186 + "description": "MARIA FALCO Zero Hour Series - Creature, 2025 numbered, titled and signed '1⁄5 \"Creature\" Maria Falco' (centre) giclee print of a graphite drawing image: 7.7 cm. high x 10 cm. wide framed: 20.5 cm. high x 25.4 cm. wide",
187 + "url": "https://www.christies.com/en/sso?ObjectID=24637.9&LotNumber=9&ldp_breadcrumb=back",
188 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0009_000(maria_falco_zero_hour_series_-_creature_2025_d6598249055047).jpg?mode=max",
189 + "estimateLow": 50,
190 + "estimateHigh": 100,
191 + "estimateText": "GBP 50 - 100",
192 + "priceRealised": 254,
193 + "priceRealisedText": "GBP 254",
194 + "startDate": "2026-08-20T00:00Z",
195 + "endDate": "2026-09-02T23:00Z",
196 + "withdrawn": false,
197 + "isOver": true
198 + },
199 + {
200 + "objectId": "6598250",
201 + "lotNumber": "10",
202 + "titlePrimary": "MARIA FALCO",
203 + "titleSecondary": "Zero Hour Series - Partner at Night, 2025",
204 + "titleTertiary": null,
205 + "description": "MARIA FALCO Zero Hour Series - Partner at Night, 2025 numbered, titled and signed '1⁄5 \"Partner At Night\" Maria Falco' (centre) giclee print of a graphite drawing image: 7.7 cm. high x 10 cm. wide framed: 20.5 cm. high x 25.4 cm. wide",
206 + "url": "https://www.christies.com/en/sso?ObjectID=24637.10&LotNumber=10&ldp_breadcrumb=back",
207 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0010_000(maria_falco_zero_hour_series_-_partner_at_night_2025054219).jpg?mode=max",
208 + "estimateLow": 50,
209 + "estimateHigh": 100,
210 + "estimateText": "GBP 50 - 100",
211 + "priceRealised": null,
212 + "priceRealisedText": null,
213 + "startDate": "2026-08-20T00:00Z",
214 + "endDate": "2026-09-02T23:00Z",
215 + "withdrawn": false,
216 + "isOver": true
217 + },
218 + {
219 + "objectId": "6598251",
220 + "lotNumber": "11",
221 + "titlePrimary": "MARIA FALCO",
222 + "titleSecondary": "Zero Hour Series - The End, 2025",
223 + "titleTertiary": null,
224 + "description": "MARIA FALCO Zero Hour Series - The End, 2025 numbered, titled and signed '1⁄5 \"The End\" Maria Falco' (centre) giclee print of a graphite drawing image: 7.7 cm. high x 10 cm. wide framed: 20.5 cm. high x 25.4 cm. wide",
225 + "url": "https://www.christies.com/en/sso?ObjectID=24637.11&LotNumber=11&ldp_breadcrumb=back",
226 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0011_000(maria_falco_zero_hour_series_-_the_end_2025054233).jpg?mode=max",
227 + "estimateLow": 50,
228 + "estimateHigh": 100,
229 + "estimateText": "GBP 50 - 100",
230 + "priceRealised": 64,
231 + "priceRealisedText": "GBP 64",
232 + "startDate": "2026-08-20T00:00Z",
233 + "endDate": "2026-09-02T23:00Z",
234 + "withdrawn": false,
235 + "isOver": true
236 + },
237 + {
238 + "objectId": "6598252",
239 + "lotNumber": "12",
240 + "titlePrimary": "SOPHIE TAYLOR",
241 + "titleSecondary": "Study of Fish Bone, 2026",
242 + "titleTertiary": null,
243 + "description": "SOPHIE TAYLOR Study of Fish Bone, 2026 signed 'SST' (lower right) pencil on paper 20.3 cm. high x 25.4 cm. wide",
244 + "url": "https://www.christies.com/en/sso?ObjectID=24637.12&LotNumber=12&ldp_breadcrumb=back",
245 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0012_000(sophie_taylor_study_of_fish_bone_2026054247).jpg?mode=max",
246 + "estimateLow": 100,
247 + "estimateHigh": 200,
248 + "estimateText": "GBP 100 - 200",
249 + "priceRealised": null,
250 + "priceRealisedText": null,
251 + "startDate": "2026-08-20T00:00Z",
252 + "endDate": "2026-09-02T23:00Z",
253 + "withdrawn": false,
254 + "isOver": true
255 + },
256 + {
257 + "objectId": "6598253",
258 + "lotNumber": "13",
259 + "titlePrimary": "EVIE JOHNSON",
260 + "titleSecondary": "3 Funky Fish, 2026",
261 + "titleTertiary": null,
262 + "description": "EVIE JOHNSON 3 Funky Fish, 2026 acrylic on canvas 55.6 cm. high x 45.7 cm. wide",
263 + "url": "https://www.christies.com/en/sso?ObjectID=24637.13&LotNumber=13&ldp_breadcrumb=back",
264 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0013_000(evie_johnson_3_funky_fish_2026054259).jpg?mode=max",
265 + "estimateLow": 300,
266 + "estimateHigh": 400,
267 + "estimateText": "GBP 300 - 400",
268 + "priceRealised": 254,
269 + "priceRealisedText": "GBP 254",
270 + "startDate": "2026-08-20T00:00Z",
271 + "endDate": "2026-09-02T23:00Z",
272 + "withdrawn": false,
273 + "isOver": true
274 + },
275 + {
276 + "objectId": "6598254",
277 + "lotNumber": "14",
278 + "titlePrimary": "MARGUERITE KNOWLES",
279 + "titleSecondary": "Fox, 2026",
280 + "titleTertiary": null,
281 + "description": "MARGUERITE KNOWLES Fox, 2026 signed 'Marguerite Knowles 2026' (on reverse) watercolour, pencil and ink on paper 21 cm. high x 14.8 cm. wide",
282 + "url": "https://www.christies.com/en/sso?ObjectID=24637.14&LotNumber=14&ldp_breadcrumb=back",
283 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0014_000(marguerite_knowles_fox_2026054312).jpg?mode=max",
284 + "estimateLow": 100,
285 + "estimateHigh": 200,
286 + "estimateText": "GBP 100 - 200",
287 + "priceRealised": 254,
288 + "priceRealisedText": "GBP 254",
289 + "startDate": "2026-08-20T00:00Z",
290 + "endDate": "2026-09-02T23:00Z",
291 + "withdrawn": false,
292 + "isOver": true
293 + },
294 + {
295 + "objectId": "6598255",
296 + "lotNumber": "15",
297 + "titlePrimary": "MARGUERITE KNOWLES",
298 + "titleSecondary": "Three Pigeons, 2026",
299 + "titleTertiary": null,
300 + "description": "MARGUERITE KNOWLES Three Pigeons, 2026 signed 'Marguerite Knowles 2026' (on reverse) watercolour, pencil and ink on paper 21 cm. high x 14.8 cm. wide",
301 + "url": "https://www.christies.com/en/sso?ObjectID=24637.15&LotNumber=15&ldp_breadcrumb=back",
302 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0015_000(marguerite_knowles_three_pigeons_2026054318).jpg?mode=max",
303 + "estimateLow": 100,
304 + "estimateHigh": 200,
305 + "estimateText": "GBP 100 - 200",
306 + "priceRealised": 190,
307 + "priceRealisedText": "GBP 190",
308 + "startDate": "2026-08-20T00:00Z",
309 + "endDate": "2026-09-02T23:00Z",
310 + "withdrawn": false,
311 + "isOver": true
312 + },
313 + {
314 + "objectId": "6598256",
315 + "lotNumber": "16",
316 + "titlePrimary": "MARGUERITE KNOWLES",
317 + "titleSecondary": "Tulip, 2026",
318 + "titleTertiary": null,
319 + "description": "MARGUERITE KNOWLES Tulip, 2026 signed 'Marguerite Knowles 2026' (on reverse) watercolour, pencil and ink on paper 21 cm. high x 14.8 cm. wide",
320 + "url": "https://www.christies.com/en/sso?ObjectID=24637.16&LotNumber=16&ldp_breadcrumb=back",
321 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0016_000(marguerite_knowles_tulip_2026054328).jpg?mode=max",
322 + "estimateLow": 100,
323 + "estimateHigh": 200,
324 + "estimateText": "GBP 100 - 200",
325 + "priceRealised": null,
326 + "priceRealisedText": null,
327 + "startDate": "2026-08-20T00:00Z",
328 + "endDate": "2026-09-02T23:00Z",
329 + "withdrawn": false,
330 + "isOver": true
331 + },
332 + {
333 + "objectId": "6598257",
334 + "lotNumber": "17",
335 + "titlePrimary": "NICHOLA JONES",
336 + "titleSecondary": "Tulip I, 2026",
337 + "titleTertiary": null,
338 + "description": "NICHOLA JONES Tulip I, 2026 watercolour and pencil on paper 22.5 cm. high x 17.5 cm. wide",
339 + "url": "https://www.christies.com/en/sso?ObjectID=24637.17&LotNumber=17&ldp_breadcrumb=back",
340 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0017_000(nichola_jones_tulip_i_2026054334).jpg?mode=max",
341 + "estimateLow": 50,
342 + "estimateHigh": 100,
343 + "estimateText": "GBP 50 - 100",
344 + "priceRealised": 64,
345 + "priceRealisedText": "GBP 64",
346 + "startDate": "2026-08-20T00:00Z",
347 + "endDate": "2026-09-02T23:00Z",
348 + "withdrawn": false,
349 + "isOver": true
350 + },
351 + {
352 + "objectId": "6598258",
353 + "lotNumber": "18",
354 + "titlePrimary": "ANNIE FOLEY",
355 + "titleSecondary": "Two Lilies",
356 + "titleTertiary": null,
357 + "description": "ANNIE FOLEY Two Lilies signed 'Annie 2023 \"TWO LILIES\"' (on reverse) oil on canvas 91 cm. high x 61 cm. wide",
358 + "url": "https://www.christies.com/en/sso?ObjectID=24637.18&LotNumber=18&ldp_breadcrumb=back",
359 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0018_000(annie_foley_two_lilies_d6598258055118).jpg?mode=max",
360 + "estimateLow": 700,
361 + "estimateHigh": 1000,
362 + "estimateText": "GBP 700 - 1,000",
363 + "priceRealised": null,
364 + "priceRealisedText": null,
365 + "startDate": "2026-08-20T00:00Z",
366 + "endDate": "2026-09-02T23:00Z",
367 + "withdrawn": false,
368 + "isOver": true
369 + },
370 + {
371 + "objectId": "6598259",
372 + "lotNumber": "19",
373 + "titlePrimary": "ISA LEUNG",
374 + "titleSecondary": "Vibrant Tulip Garden, 2026",
375 + "titleTertiary": null,
376 + "description": "ISA LEUNG Vibrant Tulip Garden, 2026 signed 'Isa' (lower right) oil on canvas 37.7 cm. high x 29 cm. wide",
377 + "url": "https://www.christies.com/en/sso?ObjectID=24637.19&LotNumber=19&ldp_breadcrumb=back",
378 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0019_000(isa_leung_vibrant_tulip_garden_2026_d6598259055124).jpg?mode=max",
379 + "estimateLow": 100,
380 + "estimateHigh": 200,
381 + "estimateText": "GBP 100 - 200",
382 + "priceRealised": null,
383 + "priceRealisedText": null,
384 + "startDate": "2026-08-20T00:00Z",
385 + "endDate": "2026-09-02T23:00Z",
386 + "withdrawn": false,
387 + "isOver": true
388 + },
389 + {
390 + "objectId": "6598260",
391 + "lotNumber": "20",
392 + "titlePrimary": "ANASTASIA LEBEDEV",
393 + "titleSecondary": "Coming Up Roses, 2026",
394 + "titleTertiary": null,
395 + "description": "ANASTASIA LEBEDEV Coming Up Roses, 2026 framed, signed, titled and dated 'Anastasia Lebedev / Coming Up Roses / 2026' (on the reverse). cyanotype print on handmade cotton paper image: 59.4 cm. high x 42 cm. wide framed: 67.4 cm. high x 50 cm. wide",
396 + "url": "https://www.christies.com/en/sso?ObjectID=24637.20&LotNumber=20&ldp_breadcrumb=back",
397 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0020_000(anastasia_lebedev_coming_up_roses_2026113705).jpg?mode=max",
398 + "estimateLow": 200,
399 + "estimateHigh": 400,
400 + "estimateText": "GBP 200 - 400",
401 + "priceRealised": null,
402 + "priceRealisedText": null,
403 + "startDate": "2026-08-20T00:00Z",
404 + "endDate": "2026-09-02T23:00Z",
405 + "withdrawn": false,
406 + "isOver": true
407 + },
408 + {
409 + "objectId": "6598261",
410 + "lotNumber": "21",
411 + "titlePrimary": "ANASTASIA LEBEDEV",
412 + "titleSecondary": "A Year of Bloom, 2026",
413 + "titleTertiary": null,
414 + "description": "ANASTASIA LEBEDEV A Year of Bloom, 2026 framed, signed, titled and dated 'Anastasia Lebedev / A Year of Bloom / 2026' (on reverse). cyanotype print on handmade cotton paper image: 42 cm. high x 59.5 cm. wide framed: 50 cm. high x 67.4 cm. wide",
415 + "url": "https://www.christies.com/en/sso?ObjectID=24637.21&LotNumber=21&ldp_breadcrumb=back",
416 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0021_000(anastasia_lebedev_a_year_of_bloom_2026061910).jpg?mode=max",
417 + "estimateLow": 200,
418 + "estimateHigh": 400,
419 + "estimateText": "GBP 200 - 400",
420 + "priceRealised": null,
421 + "priceRealisedText": null,
422 + "startDate": "2026-08-20T00:00Z",
423 + "endDate": "2026-09-02T23:00Z",
424 + "withdrawn": false,
425 + "isOver": true
426 + },
427 + {
428 + "objectId": "6598262",
429 + "lotNumber": "22",
430 + "titlePrimary": "ANASTASIA LEBEDEV",
431 + "titleSecondary": "Duallium, 2026",
432 + "titleTertiary": null,
433 + "description": "ANASTASIA LEBEDEV Duallium, 2026 diptych, framed, each print signed, titled and dated 'Anastasia Lebedev / Duallium / 2026' (on the reverse). cyanotype print on handmade cotton paper each image: 59.4 cm. high x 42 cm. wide each framed: 67.4 cm. high x 50 cm. wide",
434 + "url": "https://www.christies.com/en/sso?ObjectID=24637.22&LotNumber=22&ldp_breadcrumb=back",
435 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0022_000(anastasia_lebedev_duallium_2026062944).jpg?mode=max",
436 + "estimateLow": 300,
437 + "estimateHigh": 500,
438 + "estimateText": "GBP 300 - 500",
439 + "priceRealised": null,
440 + "priceRealisedText": null,
441 + "startDate": "2026-08-20T00:00Z",
442 + "endDate": "2026-09-02T23:00Z",
443 + "withdrawn": false,
444 + "isOver": true
445 + },
446 + {
447 + "objectId": "6598263",
448 + "lotNumber": "23",
449 + "titlePrimary": "ANASTASIA LEBEDEV",
450 + "titleSecondary": "Fall’s fall, 2026",
451 + "titleTertiary": null,
452 + "description": "ANASTASIA LEBEDEV Fall’s fall, 2026 framed, signed, titled and dated 'Anastasia Lebedev / Fall's fall / 2026' (on reverse). cyanotype print on handmade cotton paper image: 42 cm. high x 59.5 cm. wide framed: 86.5 cm. high x 62.2 cm. wide",
453 + "url": "https://www.christies.com/en/sso?ObjectID=24637.23&LotNumber=23&ldp_breadcrumb=back",
454 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0023_000(anastasia_lebedev_fall8217s_fall_2026_d6598263063041).jpg?mode=max",
455 + "estimateLow": 200,
456 + "estimateHigh": 400,
457 + "estimateText": "GBP 200 - 400",
458 + "priceRealised": 254,
459 + "priceRealisedText": "GBP 254",
460 + "startDate": "2026-08-20T00:00Z",
461 + "endDate": "2026-09-02T23:00Z",
462 + "withdrawn": false,
463 + "isOver": true
464 + },
465 + {
466 + "objectId": "6598264",
467 + "lotNumber": "24",
468 + "titlePrimary": "ANASTASIA LEBEDEV",
469 + "titleSecondary": "From Eden, 2026",
470 + "titleTertiary": null,
471 + "description": "ANASTASIA LEBEDEV From Eden, 2026 diptych, framed, each print signed, titled and dated 'Anastasia Lebedev / From Eden / 2026' (on reverse). cyanotype print on handmade cotton paper each image: 59.4 cm. high x 42 cm. wide each framed: 67.4 cm. high x 50 cm. wide",
472 + "url": "https://www.christies.com/en/sso?ObjectID=24637.24&LotNumber=24&ldp_breadcrumb=back",
473 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0024_000(anastasia_levedev_from_eden_d6598264063058).jpg?mode=max",
474 + "estimateLow": 300,
475 + "estimateHigh": 500,
476 + "estimateText": "GBP 300 - 500",
477 + "priceRealised": null,
478 + "priceRealisedText": null,
479 + "startDate": "2026-08-20T00:00Z",
480 + "endDate": "2026-09-02T23:00Z",
481 + "withdrawn": false,
482 + "isOver": true
483 + },
484 + {
485 + "objectId": "6598265",
486 + "lotNumber": "25",
487 + "titlePrimary": "RAFFAELE COLETTA",
488 + "titleSecondary": "Piera, 2024",
489 + "titleTertiary": null,
490 + "description": "RAFFAELE COLETTA Piera, 2024 signed 'R.Coletta' (on reverse) oil on canvas 76 cm. high x 60 cm. wide",
491 + "url": "https://www.christies.com/en/sso?ObjectID=24637.25&LotNumber=25&ldp_breadcrumb=back",
492 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0025_000(raffaele_coletta_piera_2024_d6598265055235).jpg?mode=max",
493 + "estimateLow": 400,
494 + "estimateHigh": 600,
495 + "estimateText": "GBP 400 - 600",
496 + "priceRealised": 64,
497 + "priceRealisedText": "GBP 64",
498 + "startDate": "2026-08-20T00:00Z",
499 + "endDate": "2026-09-02T23:00Z",
500 + "withdrawn": false,
501 + "isOver": true
502 + },
503 + {
504 + "objectId": "6598266",
505 + "lotNumber": "26",
506 + "titlePrimary": "RAFFAELE COLETTA",
507 + "titleSecondary": "Miranda, 2025",
508 + "titleTertiary": null,
509 + "description": "RAFFAELE COLETTA Miranda, 2025 signed 'R.Coletta' (on reverse) oil on canvas 76 cm. high x 60 cm. wide",
510 + "url": "https://www.christies.com/en/sso?ObjectID=24637.26&LotNumber=26&ldp_breadcrumb=back",
511 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0026_000(raffaele_coletta_miranda_2025_d6598266055243).jpg?mode=max",
512 + "estimateLow": 400,
513 + "estimateHigh": 600,
514 + "estimateText": "GBP 400 - 600",
515 + "priceRealised": 64,
516 + "priceRealisedText": "GBP 64",
517 + "startDate": "2026-08-20T00:00Z",
518 + "endDate": "2026-09-02T23:00Z",
519 + "withdrawn": false,
520 + "isOver": true
521 + },
522 + {
523 + "objectId": "6598267",
524 + "lotNumber": "27",
525 + "titlePrimary": "RAFFAELE COLETTA",
526 + "titleSecondary": "Yu-Ge, 2025",
527 + "titleTertiary": null,
528 + "description": "RAFFAELE COLETTA Yu-Ge, 2025 signed 'R. Coletta' (on reverse) oil on canvas 76 cm. high x 60 cm. wide",
529 + "url": "https://www.christies.com/en/sso?ObjectID=24637.27&LotNumber=27&ldp_breadcrumb=back",
530 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0027_000(raffaele_coletta_yu-ge_2025_d6598267055251).jpg?mode=max",
531 + "estimateLow": 400,
532 + "estimateHigh": 600,
533 + "estimateText": "GBP 400 - 600",
534 + "priceRealised": 318,
535 + "priceRealisedText": "GBP 318",
536 + "startDate": "2026-08-20T00:00Z",
537 + "endDate": "2026-09-02T23:00Z",
538 + "withdrawn": false,
539 + "isOver": true
540 + },
541 + {
542 + "objectId": "6598268",
543 + "lotNumber": "28",
544 + "titlePrimary": "GUILLEM MATALLANAS",
545 + "titleSecondary": "GENERATION C2, 2019",
546 + "titleTertiary": null,
547 + "description": "GUILLEM MATALLANAS GENERATION C2, 2019 screenprint on paper 42 cm. high x 59.4 cm. wide",
548 + "url": "https://www.christies.com/en/sso?ObjectID=24637.28&LotNumber=28&ldp_breadcrumb=back",
549 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0028_000(guillem_matallanas_generation_c2_2019054438).jpg?mode=max",
550 + "estimateLow": 400,
551 + "estimateHigh": 500,
552 + "estimateText": "GBP 400 - 500",
553 + "priceRealised": 254,
554 + "priceRealisedText": "GBP 254",
555 + "startDate": "2026-08-20T00:00Z",
556 + "endDate": "2026-09-02T23:00Z",
557 + "withdrawn": false,
558 + "isOver": true
559 + },
560 + {
561 + "objectId": "6598269",
562 + "lotNumber": "29",
563 + "titlePrimary": "GRAEME DUDDRIDGE",
564 + "titleSecondary": "Stargazer, 2024",
565 + "titleTertiary": null,
566 + "description": "GRAEME DUDDRIDGE Stargazer, 2024 pencil, watercolour, collage &amp; metal leaf on paper framed: 50.6 cm. high x 70.6 cm. wide",
567 + "url": "https://www.christies.com/en/sso?ObjectID=24637.29&LotNumber=29&ldp_breadcrumb=back",
568 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0029_000(graeme_duddridge_stargazer_2024054445).jpg?mode=max",
569 + "estimateLow": 500,
570 + "estimateHigh": 800,
571 + "estimateText": "GBP 500 - 800",
572 + "priceRealised": null,
573 + "priceRealisedText": null,
574 + "startDate": "2026-08-20T00:00Z",
575 + "endDate": "2026-09-02T23:00Z",
576 + "withdrawn": false,
577 + "isOver": true
578 + },
579 + {
580 + "objectId": "6598270",
581 + "lotNumber": "30",
582 + "titlePrimary": "GRAEME DUDDRIDGE",
583 + "titleSecondary": "Ellie in Stripes, 2025",
584 + "titleTertiary": null,
585 + "description": "GRAEME DUDDRIDGE Ellie in Stripes, 2025 oil on board, artist frame in walnut, corian inlay and vintage buttons framed: 65.1 cm. high x 55.5 cm. wide",
586 + "url": "https://www.christies.com/en/sso?ObjectID=24637.30&LotNumber=30&ldp_breadcrumb=back",
587 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0030_000(graeme_duddridge_ellie_in_stripes_2025055306).jpg?mode=max",
588 + "estimateLow": 800,
589 + "estimateHigh": 1000,
590 + "estimateText": "GBP 800 - 1,000",
591 + "priceRealised": null,
592 + "priceRealisedText": null,
593 + "startDate": "2026-08-20T00:00Z",
594 + "endDate": "2026-09-02T23:00Z",
595 + "withdrawn": false,
596 + "isOver": true
597 + },
598 + {
599 + "objectId": "6598271",
600 + "lotNumber": "31",
601 + "titlePrimary": "GRAEME DUDDRIDGE",
602 + "titleSecondary": "Serving Fish, 2019",
603 + "titleTertiary": null,
604 + "description": "GRAEME DUDDRIDGE Serving Fish, 2019 signed 'GD' 19 Serving Fish' (on reverse) oil on board 40 cm. high x 28 cm. wide x 3.5 cm. deep",
605 + "url": "https://www.christies.com/en/sso?ObjectID=24637.31&LotNumber=31&ldp_breadcrumb=back",
606 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0031_000(graeme_duddridge_serving_fish_2019055322).jpg?mode=max",
607 + "estimateLow": 500,
608 + "estimateHigh": 800,
609 + "estimateText": "GBP 500 - 800",
610 + "priceRealised": 635,
611 + "priceRealisedText": "GBP 635",
612 + "startDate": "2026-08-20T00:00Z",
613 + "endDate": "2026-09-02T23:00Z",
614 + "withdrawn": false,
615 + "isOver": true
616 + },
617 + {
618 + "objectId": "6598272",
619 + "lotNumber": "32",
620 + "titlePrimary": "ALICE GELDENHUYS",
621 + "titleSecondary": "Embrace, 2025",
622 + "titleTertiary": null,
623 + "description": "ALICE GELDENHUYS Embrace, 2025 signed 'ALICE G'25' (on reverse) acrylic on canvas 42 cm. high x 29.5 cm. wide",
624 + "url": "https://www.christies.com/en/sso?ObjectID=24637.32&LotNumber=32&ldp_breadcrumb=back",
625 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0032_000(alice_geldenhuys_embrace_2025055334).jpg?mode=max",
626 + "estimateLow": 200,
627 + "estimateHigh": 300,
628 + "estimateText": "GBP 200 - 300",
629 + "priceRealised": null,
630 + "priceRealisedText": null,
631 + "startDate": "2026-08-20T00:00Z",
632 + "endDate": "2026-09-02T23:00Z",
633 + "withdrawn": false,
634 + "isOver": true
635 + },
636 + {
637 + "objectId": "6598273",
638 + "lotNumber": "33",
639 + "titlePrimary": "ALICE GELDENHUYS",
640 + "titleSecondary": "Stretch, 2025",
641 + "titleTertiary": null,
642 + "description": "ALICE GELDENHUYS Stretch, 2025 signed 'ALICE G'25' (on reverse) acrylic on canvas 30.5 cm. high x 41 cm. wide",
643 + "url": "https://www.christies.com/en/sso?ObjectID=24637.33&LotNumber=33&ldp_breadcrumb=back",
644 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0033_000(alice_geldenhuys_stretch_2025_d6598273055347).jpg?mode=max",
645 + "estimateLow": 200,
646 + "estimateHigh": 300,
647 + "estimateText": "GBP 200 - 300",
648 + "priceRealised": null,
649 + "priceRealisedText": null,
650 + "startDate": "2026-08-20T00:00Z",
651 + "endDate": "2026-09-02T23:00Z",
652 + "withdrawn": false,
653 + "isOver": true
654 + },
655 + {
656 + "objectId": "6598274",
657 + "lotNumber": "34",
658 + "titlePrimary": "ALICE KIM",
659 + "titleSecondary": "O-mi, 2026",
660 + "titleTertiary": null,
661 + "description": "ALICE KIM O-mi, 2026 Korean traditional organza (ramie and hemp) 21 cm. high x 40 cm. wide",
662 + "url": "https://www.christies.com/en/sso?ObjectID=24637.34&LotNumber=34&ldp_breadcrumb=back",
663 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0034_000(alice_kim_o-mi_2026055354).jpg?mode=max",
664 + "estimateLow": 700,
665 + "estimateHigh": 900,
666 + "estimateText": "GBP 700 - 900",
667 + "priceRealised": 508,
668 + "priceRealisedText": "GBP 508",
669 + "startDate": "2026-08-20T00:00Z",
670 + "endDate": "2026-09-02T23:00Z",
671 + "withdrawn": false,
672 + "isOver": true
673 + },
674 + {
675 + "objectId": "6598275",
676 + "lotNumber": "35",
677 + "titlePrimary": "JAMES CAMPION",
678 + "titleSecondary": "After Mondrian, 2019",
679 + "titleTertiary": null,
680 + "description": "JAMES CAMPION After Mondrian, 2019 signed 'Campion 2019' (on reverse) oil on canvas 30 cm. high x 30 cm. wide",
681 + "url": "https://www.christies.com/en/sso?ObjectID=24637.35&LotNumber=35&ldp_breadcrumb=back",
682 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0035_000(james_campion_after_mondrian_2019_d6598275055400).jpg?mode=max",
683 + "estimateLow": 600,
684 + "estimateHigh": 800,
685 + "estimateText": "GBP 600 - 800",
686 + "priceRealised": null,
687 + "priceRealisedText": null,
688 + "startDate": "2026-08-20T00:00Z",
689 + "endDate": "2026-09-02T23:00Z",
690 + "withdrawn": false,
691 + "isOver": true
692 + },
693 + {
694 + "objectId": "6598276",
695 + "lotNumber": "36",
696 + "titlePrimary": "JAMES CAMPION",
697 + "titleSecondary": "Towel Painting, 2026",
698 + "titleTertiary": null,
699 + "description": "JAMES CAMPION Towel Painting, 2026 signed 'TOWEL PAINTING I/James Campion 2026' (on reverse) oil on canvas 50 cm. high x 60 cm. wide",
700 + "url": "https://www.christies.com/en/sso?ObjectID=24637.36&LotNumber=36&ldp_breadcrumb=back",
701 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0036_000(james_campion_towel_painting_2026_d6598276055410).jpg?mode=max",
702 + "estimateLow": 800,
703 + "estimateHigh": 1000,
704 + "estimateText": "GBP 800 - 1,000",
705 + "priceRealised": null,
706 + "priceRealisedText": null,
707 + "startDate": "2026-08-20T00:00Z",
708 + "endDate": "2026-09-02T23:00Z",
709 + "withdrawn": false,
710 + "isOver": true
711 + },
712 + {
713 + "objectId": "6598277",
714 + "lotNumber": "37",
715 + "titlePrimary": "JAMES CAMPION",
716 + "titleSecondary": "Towel Painting II, 2026",
717 + "titleTertiary": null,
718 + "description": "JAMES CAMPION Towel Painting II, 2026 signed 'TOWEL PAINTING II/ James Campion 2026' (on reverse) oil on canvas 60 cm. high x 50 cm. wide",
719 + "url": "https://www.christies.com/en/sso?ObjectID=24637.37&LotNumber=37&ldp_breadcrumb=back",
720 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0037_000(james_campion_towel_painting_ii_2026_d6598277055417).jpg?mode=max",
721 + "estimateLow": 800,
722 + "estimateHigh": 1000,
723 + "estimateText": "GBP 800 - 1,000",
724 + "priceRealised": null,
725 + "priceRealisedText": null,
726 + "startDate": "2026-08-20T00:00Z",
727 + "endDate": "2026-09-02T23:00Z",
728 + "withdrawn": false,
729 + "isOver": true
730 + },
731 + {
732 + "objectId": "6598278",
733 + "lotNumber": "38",
734 + "titlePrimary": "BRONWEN HARRISON",
735 + "titleSecondary": "Tidal Vessel",
736 + "titleTertiary": null,
737 + "description": "BRONWEN HARRISON Tidal Vessel glazed stonewear 18 cm. high x 13 cm. wide x 6 cm. deep",
738 + "url": "https://www.christies.com/en/sso?ObjectID=24637.38&LotNumber=38&ldp_breadcrumb=back",
739 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0038_000(bronwen_harrison_tidal_vessel054518).jpg?mode=max",
740 + "estimateLow": 100,
741 + "estimateHigh": 200,
742 + "estimateText": "GBP 100 - 200",
743 + "priceRealised": 127,
744 + "priceRealisedText": "GBP 127",
745 + "startDate": "2026-08-20T00:00Z",
746 + "endDate": "2026-09-02T23:00Z",
747 + "withdrawn": false,
748 + "isOver": true
749 + },
750 + {
751 + "objectId": "6598279",
752 + "lotNumber": "39",
753 + "titlePrimary": "BRONWEN HARRISON",
754 + "titleSecondary": "Tidal Vessel II",
755 + "titleTertiary": null,
756 + "description": "BRONWEN HARRISON Tidal Vessel II glazed stoneware 13 cm. high x 14 cm. wide x 13 cm. deep",
757 + "url": "https://www.christies.com/en/sso?ObjectID=24637.39&LotNumber=39&ldp_breadcrumb=back",
758 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0039_000(bronwen_harrison_tidal_vessel_ii054524).jpg?mode=max",
759 + "estimateLow": 100,
760 + "estimateHigh": 200,
761 + "estimateText": "GBP 100 - 200",
762 + "priceRealised": 254,
763 + "priceRealisedText": "GBP 254",
764 + "startDate": "2026-08-20T00:00Z",
765 + "endDate": "2026-09-02T23:00Z",
766 + "withdrawn": false,
767 + "isOver": true
768 + },
769 + {
770 + "objectId": "6598280",
771 + "lotNumber": "40",
772 + "titlePrimary": "BRONWEN HARRISON",
773 + "titleSecondary": "Upside-down Bowl",
774 + "titleTertiary": null,
775 + "description": "BRONWEN HARRISON Upside-down Bowl glazed stoneware 19 cm. high x 38 cm. wide x 13 cm. deep",
776 + "url": "https://www.christies.com/en/sso?ObjectID=24637.40&LotNumber=40&ldp_breadcrumb=back",
777 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0040_000(bronwen_harrison_upside-down_bowl054530).jpg?mode=max",
778 + "estimateLow": 100,
779 + "estimateHigh": 200,
780 + "estimateText": "GBP 100 - 200",
781 + "priceRealised": 127,
782 + "priceRealisedText": "GBP 127",
783 + "startDate": "2026-08-20T00:00Z",
784 + "endDate": "2026-09-02T23:00Z",
785 + "withdrawn": false,
786 + "isOver": true
787 + },
788 + {
789 + "objectId": "6598281",
790 + "lotNumber": "41",
791 + "titlePrimary": "SANDRA ROMITO",
792 + "titleSecondary": "Toto's Vases",
793 + "titleTertiary": null,
794 + "description": "SANDRA ROMITO Toto's Vases ceramic 30 cm. high x 20 cm. wide x 20 cm. deep(3)",
795 + "url": "https://www.christies.com/en/sso?ObjectID=24637.41&LotNumber=41&ldp_breadcrumb=back",
796 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0041_000(sandra_romito_totos_vases054547).jpg?mode=max",
797 + "estimateLow": 400,
798 + "estimateHigh": 600,
799 + "estimateText": "GBP 400 - 600",
800 + "priceRealised": 508,
801 + "priceRealisedText": "GBP 508",
802 + "startDate": "2026-08-20T00:00Z",
803 + "endDate": "2026-09-02T23:00Z",
804 + "withdrawn": false,
805 + "isOver": true
806 + },
807 + {
808 + "objectId": "6598282",
809 + "lotNumber": "42",
810 + "titlePrimary": "PRAPASRI SUWANNAKHOT",
811 + "titleSecondary": "Experimental - Ripley, 2026",
812 + "titleTertiary": null,
813 + "description": "PRAPASRI SUWANNAKHOT Experimental - Ripley, 2026 pendant, charm freshwater baroque pearl, silver, cubic zirconia 2 cm. high x 2.7 cm. wide x 0.5 cm. deep",
814 + "url": "https://www.christies.com/en/sso?ObjectID=24637.42&LotNumber=42&ldp_breadcrumb=back",
815 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0042_000(prapasri_suwannakhot_experimental_-_ripley_2026055534).jpg?mode=max",
816 + "estimateLow": 50,
817 + "estimateHigh": 100,
818 + "estimateText": "GBP 50 - 100",
819 + "priceRealised": 64,
820 + "priceRealisedText": "GBP 64",
821 + "startDate": "2026-08-20T00:00Z",
822 + "endDate": "2026-09-02T23:00Z",
823 + "withdrawn": false,
824 + "isOver": true
825 + },
826 + {
827 + "objectId": "6598283",
828 + "lotNumber": "43",
829 + "titlePrimary": "PRAPASRI SUWANNAKHOT",
830 + "titleSecondary": "RGB Chameleon Pendant Necklace, 2022",
831 + "titleTertiary": null,
832 + "description": "PRAPASRI SUWANNAKHOT RGB Chameleon Pendant Necklace, 2022 made in 2022, UK hallmarked 2026 diamond, colourless sapphire, garnet, mystic topaz, cold enamel pendant on foxtail chain mystic topaz is a natural colourless topaz stone enhanced with a thin metallic coating pendant: 2.6 cm. high x 1.8 cm. wide x 1.1 cm. deep chain: 51.4 cm. lengh",
833 + "url": "https://www.christies.com/en/sso?ObjectID=24637.43&LotNumber=43&ldp_breadcrumb=back",
834 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0043_000(prapasri_suwannakhot_rgb_chameleon_pendant_necklace_2022054617).jpg?mode=max",
835 + "estimateLow": 700,
836 + "estimateHigh": 900,
837 + "estimateText": "GBP 700 - 900",
838 + "priceRealised": 1143,
839 + "priceRealisedText": "GBP 1,143",
840 + "startDate": "2026-08-20T00:00Z",
841 + "endDate": "2026-09-02T23:00Z",
842 + "withdrawn": false,
843 + "isOver": true
844 + },
845 + {
846 + "objectId": "6598284",
847 + "lotNumber": "44",
848 + "titlePrimary": "PRAPASRI SUWANNAKHOT",
849 + "titleSecondary": "Mystic Ring - Chameleon Ring, 2022",
850 + "titleTertiary": null,
851 + "description": "PRAPASRI SUWANNAKHOT Mystic Ring - Chameleon Ring, 2022 made in 2022, UK hallmarked 2026 mystic topaz, silver, sapphires mystic topaz is a natural colourless topaz stone enhanced with a thin metallic coating 2.7 cm. high x 2.5 cm. wide x 5.2 cm. deep ring size: EU 60, UK S, US 9 not recommend for resizing due to stone settings",
852 + "url": "https://www.christies.com/en/sso?ObjectID=24637.44&LotNumber=44&ldp_breadcrumb=back",
853 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0044_000(prapasri_suwannakhot_mystic_ring_-_chameleon_ring_2022_d6598284055608).jpg?mode=max",
854 + "estimateLow": 700,
855 + "estimateHigh": 900,
856 + "estimateText": "GBP 700 - 900",
857 + "priceRealised": 762,
858 + "priceRealisedText": "GBP 762",
859 + "startDate": "2026-08-20T00:00Z",
860 + "endDate": "2026-09-02T23:00Z",
861 + "withdrawn": false,
862 + "isOver": true
863 + },
864 + {
865 + "objectId": "6598285",
866 + "lotNumber": "45",
867 + "titlePrimary": "PRAPASRI SUWANNAKHOT",
868 + "titleSecondary": "Half Eternity Orange Sapphire, 2023",
869 + "titleTertiary": null,
870 + "description": "PRAPASRI SUWANNAKHOT Half Eternity Orange Sapphire, 2023 UK hallmarked, 2023 coloured diamonds, orange sapphire, silver, yellow gold plating 2 cm. high x 0.56 cm. wide x 2.2 cm. deep ring size: EU 57, UK Q, US 8 not recommend for resizing due to stone settings",
871 + "url": "https://www.christies.com/en/sso?ObjectID=24637.45&LotNumber=45&ldp_breadcrumb=back",
872 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0045_000(prapasri_suwannakhot_half_eternity_orange_sapphire_2023_d6598285055614).jpg?mode=max",
873 + "estimateLow": 300,
874 + "estimateHigh": 500,
875 + "estimateText": "GBP 300 - 500",
876 + "priceRealised": 318,
877 + "priceRealisedText": "GBP 318",
878 + "startDate": "2026-08-20T00:00Z",
879 + "endDate": "2026-09-02T23:00Z",
880 + "withdrawn": false,
881 + "isOver": true
882 + },
883 + {
884 + "objectId": "6598286",
885 + "lotNumber": "46",
886 + "titlePrimary": "PRAPASRI SUWANNAKHOT",
887 + "titleSecondary": "TzTs ring, 2023",
888 + "titleTertiary": null,
889 + "description": "PRAPASRI SUWANNAKHOT TzTs ring, 2023 UK hallmarked, 2023 silver, tanzanite, tsavorite 2.37 cm. high x 1.0 cm. wide x 2.31 cm. deep ring size: EU 57, UK Q, US 8 not recommend for resizing due to stone settings",
890 + "url": "https://www.christies.com/en/sso?ObjectID=24637.46&LotNumber=46&ldp_breadcrumb=back",
891 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0046_000(prapasri_suwannakhot_tzts_ring_2023_d6598286055620).jpg?mode=max",
892 + "estimateLow": 400,
893 + "estimateHigh": 600,
894 + "estimateText": "GBP 400 - 600",
895 + "priceRealised": 254,
896 + "priceRealisedText": "GBP 254",
897 + "startDate": "2026-08-20T00:00Z",
898 + "endDate": "2026-09-02T23:00Z",
899 + "withdrawn": false,
900 + "isOver": true
901 + },
902 + {
903 + "objectId": "6598287",
904 + "lotNumber": "47",
905 + "titlePrimary": "LUCIA ALONSO-LASHERAS SMITH",
906 + "titleSecondary": "Chez Richard, 2026",
907 + "titleTertiary": null,
908 + "description": "LUCIA ALONSO-LASHERAS SMITH Chez Richard, 2026 oil on canvas board 32.8 cm. high x 24.4 cm. wide",
909 + "url": "https://www.christies.com/en/sso?ObjectID=24637.47&LotNumber=47&ldp_breadcrumb=back",
910 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0047_000(lucia_alonso-lasheras_smith_chez_richard_2026_d6598287055628).jpg?mode=max",
911 + "estimateLow": 100,
912 + "estimateHigh": 200,
913 + "estimateText": "GBP 100 - 200",
914 + "priceRealised": 381,
915 + "priceRealisedText": "GBP 381",
916 + "startDate": "2026-08-20T00:00Z",
917 + "endDate": "2026-09-02T23:00Z",
918 + "withdrawn": false,
919 + "isOver": true
920 + },
921 + {
922 + "objectId": "6598288",
923 + "lotNumber": "48",
924 + "titlePrimary": "RUTH ANDERTON",
925 + "titleSecondary": "In the Noodle Bar, 2026",
926 + "titleTertiary": null,
927 + "description": "RUTH ANDERTON In the Noodle Bar, 2026 signed 'Ruth S. Anderton 2026' (on reverse) oil on canvas 30 cm. high x 30 cm. wide",
928 + "url": "https://www.christies.com/en/sso?ObjectID=24637.48&LotNumber=48&ldp_breadcrumb=back",
929 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0048_000(ruth_anderton_in_the_noodle_bar_2026054717).jpg?mode=max",
930 + "estimateLow": 400,
931 + "estimateHigh": 600,
932 + "estimateText": "GBP 400 - 600",
933 + "priceRealised": 381,
934 + "priceRealisedText": "GBP 381",
935 + "startDate": "2026-08-20T00:00Z",
936 + "endDate": "2026-09-02T23:00Z",
937 + "withdrawn": false,
938 + "isOver": true
939 + },
940 + {
941 + "objectId": "6598289",
942 + "lotNumber": "49",
943 + "titlePrimary": "SOPHIE KHAN",
944 + "titleSecondary": "Anonymous, 2026",
945 + "titleTertiary": null,
946 + "description": "SOPHIE KHAN Anonymous, 2026 35mm photograph on hahnemühle paper framed: 32.6 cm. high x 23.9 cm. wide",
947 + "url": "https://www.christies.com/en/sso?ObjectID=24637.49&LotNumber=49&ldp_breadcrumb=back",
948 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0049_000(sophie_khan_anonymous_2026054731).jpg?mode=max",
949 + "estimateLow": 100,
950 + "estimateHigh": 200,
951 + "estimateText": "GBP 100 - 200",
952 + "priceRealised": 64,
953 + "priceRealisedText": "GBP 64",
954 + "startDate": "2026-08-20T00:00Z",
955 + "endDate": "2026-09-02T23:00Z",
956 + "withdrawn": false,
957 + "isOver": true
958 + },
959 + {
960 + "objectId": "6598290",
961 + "lotNumber": "50",
962 + "titlePrimary": "SOPHIE KHAN",
963 + "titleSecondary": "Path, 2026",
964 + "titleTertiary": null,
965 + "description": "SOPHIE KHAN Path, 2026 35mm photograph on hahnemühle paper framed: 44.6 cm. high x 32.5 cm. wide",
966 + "url": "https://www.christies.com/en/sso?ObjectID=24637.50&LotNumber=50&ldp_breadcrumb=back",
967 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0050_000(sophie_khan_path_2026055642).jpg?mode=max",
968 + "estimateLow": 100,
969 + "estimateHigh": 200,
970 + "estimateText": "GBP 100 - 200",
971 + "priceRealised": 64,
972 + "priceRealisedText": "GBP 64",
973 + "startDate": "2026-08-20T00:00Z",
974 + "endDate": "2026-09-02T23:00Z",
975 + "withdrawn": false,
976 + "isOver": true
977 + },
978 + {
979 + "objectId": "6598291",
980 + "lotNumber": "51",
981 + "titlePrimary": "SOPHIE KHAN",
982 + "titleSecondary": "Moke, 2026",
983 + "titleTertiary": null,
984 + "description": "SOPHIE KHAN Moke, 2026 35mm photograph on hahnemühle paper framed: 44.6 cm. high x 32.5 cm. wide",
985 + "url": "https://www.christies.com/en/sso?ObjectID=24637.51&LotNumber=51&ldp_breadcrumb=back",
986 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0051_000(sophie_khan_moke_2026_d6598291055657).jpg?mode=max",
987 + "estimateLow": 100,
988 + "estimateHigh": 200,
989 + "estimateText": "GBP 100 - 200",
990 + "priceRealised": 127,
991 + "priceRealisedText": "GBP 127",
992 + "startDate": "2026-08-20T00:00Z",
993 + "endDate": "2026-09-02T23:00Z",
994 + "withdrawn": false,
995 + "isOver": true
996 + },
997 + {
998 + "objectId": "6598292",
999 + "lotNumber": "52",
1000 + "titlePrimary": "NATASHA WILCOCKSON",
1001 + "titleSecondary": "Fallow Year, 2026",
1002 + "titleTertiary": null,
1003 + "description": "NATASHA WILCOCKSON Fallow Year, 2026 signed 'NW' (lower right) and '\"Fallow Year\" July 2026 Natasha Wilcockson' (on reverse) acrylic on canvas 50 cm. high x 40 cm. wide",
1004 + "url": "https://www.christies.com/en/sso?ObjectID=24637.52&LotNumber=52&ldp_breadcrumb=back",
1005 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0052_000(natasha_wilcockson_fallow_year_2026055705).jpg?mode=max",
1006 + "estimateLow": 100,
1007 + "estimateHigh": 200,
1008 + "estimateText": "GBP 100 - 200",
1009 + "priceRealised": 190,
1010 + "priceRealisedText": "GBP 190",
1011 + "startDate": "2026-08-20T00:00Z",
1012 + "endDate": "2026-09-02T23:00Z",
1013 + "withdrawn": false,
1014 + "isOver": true
1015 + },
1016 + {
1017 + "objectId": "6598293",
1018 + "lotNumber": "53",
1019 + "titlePrimary": "NJALL MILLEN",
1020 + "titleSecondary": "Clifton Nurseries, Maida Vale (Saturn glimpsed at pink dawn)",
1021 + "titleTertiary": null,
1022 + "description": "NJALL MILLEN Clifton Nurseries, Maida Vale (Saturn glimpsed at pink dawn) signed 'Njall Millen 2026' (on reverse) oil on canvas 50 cm. high x 40 cm. wide",
1023 + "url": "https://www.christies.com/en/sso?ObjectID=24637.53&LotNumber=53&ldp_breadcrumb=back",
1024 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0053_000(neil_millen_clifton_nurseries_maida_vale055719).jpg?mode=max",
1025 + "estimateLow": 500,
1026 + "estimateHigh": 800,
1027 + "estimateText": "GBP 500 - 800",
1028 + "priceRealised": 635,
1029 + "priceRealisedText": "GBP 635",
1030 + "startDate": "2026-08-20T00:00Z",
1031 + "endDate": "2026-09-02T23:00Z",
1032 + "withdrawn": false,
1033 + "isOver": true
1034 + },
1035 + {
1036 + "objectId": "6598294",
1037 + "lotNumber": "54",
1038 + "titlePrimary": "NJALL MILLEN",
1039 + "titleSecondary": "Dawn from the Artist's Window (A Clatter of Jackdaws, Cornwall), 2026",
1040 + "titleTertiary": null,
1041 + "description": "NJALL MILLEN Dawn from the Artist's Window (A Clatter of Jackdaws, Cornwall), 2026 signed 'Njall Millen 2026' (on reverse) oil on canvas 40 cm. high x 30 cm. wide",
1042 + "url": "https://www.christies.com/en/sso?ObjectID=24637.54&LotNumber=54&ldp_breadcrumb=back",
1043 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0054_000(neil_millen_duallium_2026054744).jpg?mode=max",
1044 + "estimateLow": 400,
1045 + "estimateHigh": 700,
1046 + "estimateText": "GBP 400 - 700",
1047 + "priceRealised": 508,
1048 + "priceRealisedText": "GBP 508",
1049 + "startDate": "2026-08-20T00:00Z",
1050 + "endDate": "2026-09-02T23:00Z",
1051 + "withdrawn": false,
1052 + "isOver": true
1053 + },
1054 + {
1055 + "objectId": "6598295",
1056 + "lotNumber": "55",
1057 + "titlePrimary": "NJALL MILLEN",
1058 + "titleSecondary": "Lone Raven over Fields, St Agnes Beacon, with Copper Clouds, 2026",
1059 + "titleTertiary": null,
1060 + "description": "NJALL MILLEN Lone Raven over Fields, St Agnes Beacon, with Copper Clouds, 2026 signed 'Njall Millen 2026' (on reverse) oil on canvas 30 cm. high x 40 cm. wide",
1061 + "url": "https://www.christies.com/en/sso?ObjectID=24637.55&LotNumber=55&ldp_breadcrumb=back",
1062 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0055_000(neil_millen_lone_raven_over_fields_st_agnes_beacon_with_copper_clouds054751).jpg?mode=max",
1063 + "estimateLow": 400,
1064 + "estimateHigh": 700,
1065 + "estimateText": "GBP 400 - 700",
1066 + "priceRealised": null,
1067 + "priceRealisedText": null,
1068 + "startDate": "2026-08-20T00:00Z",
1069 + "endDate": "2026-09-02T23:00Z",
1070 + "withdrawn": false,
1071 + "isOver": true
1072 + },
1073 + {
1074 + "objectId": "6598296",
1075 + "lotNumber": "56",
1076 + "titlePrimary": "COOKIE BERGMAN",
1077 + "titleSecondary": "We Are Starstuff",
1078 + "titleTertiary": null,
1079 + "description": "COOKIE BERGMAN We Are Starstuff signed as edition 1⁄7 Print on Aluminium Dibond, Black Oak Artbox frame. Digital collage print size: 21 cm. high x 20 cm. wide framed: 21.8 high x 20.8 cm wide",
1080 + "url": "https://www.christies.com/en/sso?ObjectID=24637.56&LotNumber=56&ldp_breadcrumb=back",
1081 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0056_000(cookie_bergman_we_are_starstuff_d6598296055735).jpg?mode=max",
1082 + "estimateLow": 300,
1083 + "estimateHigh": 500,
1084 + "estimateText": "GBP 300 - 500",
1085 + "priceRealised": 254,
1086 + "priceRealisedText": "GBP 254",
1087 + "startDate": "2026-08-20T00:00Z",
1088 + "endDate": "2026-09-02T23:00Z",
1089 + "withdrawn": false,
1090 + "isOver": true
1091 + },
1092 + {
1093 + "objectId": "6598297",
1094 + "lotNumber": "57",
1095 + "titlePrimary": "COOKIE BERGMAN",
1096 + "titleSecondary": "Postcard from a Speculative Past",
1097 + "titleTertiary": null,
1098 + "description": "COOKIE BERGMAN Postcard from a Speculative Past signed as edition 1⁄7 framed, photography, giclée fine art print 17.8 cm. high x 29.7 cm. wide (print dimensions without frame)",
1099 + "url": "https://www.christies.com/en/sso?ObjectID=24637.57&LotNumber=57&ldp_breadcrumb=back",
1100 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0057_000(cookie_bergman_postcard_from_a_speculative_past054811).jpg?mode=max",
1101 + "estimateLow": 300,
1102 + "estimateHigh": 500,
1103 + "estimateText": "GBP 300 - 500",
1104 + "priceRealised": 254,
1105 + "priceRealisedText": "GBP 254",
1106 + "startDate": "2026-08-20T00:00Z",
1107 + "endDate": "2026-09-02T23:00Z",
1108 + "withdrawn": false,
1109 + "isOver": true
1110 + },
1111 + {
1112 + "objectId": "6598298",
1113 + "lotNumber": "58",
1114 + "titlePrimary": "SHARON SMART",
1115 + "titleSecondary": "Seascape I, 2019",
1116 + "titleTertiary": null,
1117 + "description": "SHARON SMART Seascape I, 2019 signed 'Smart '19' (lower right) pencil on paper framed: 22.5 cm. high x 26.5 cm. wide",
1118 + "url": "https://www.christies.com/en/sso?ObjectID=24637.58&LotNumber=58&ldp_breadcrumb=back",
1119 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0058_000(sharon_smart_seascape_i_2019054823).jpg?mode=max",
1120 + "estimateLow": 100,
1121 + "estimateHigh": 200,
1122 + "estimateText": "GBP 100 - 200",
1123 + "priceRealised": null,
1124 + "priceRealisedText": null,
1125 + "startDate": "2026-08-20T00:00Z",
1126 + "endDate": "2026-09-02T23:00Z",
1127 + "withdrawn": false,
1128 + "isOver": true
1129 + },
1130 + {
1131 + "objectId": "6598299",
1132 + "lotNumber": "59",
1133 + "titlePrimary": "SHARON SMART",
1134 + "titleSecondary": "Seascape IV, 2019",
1135 + "titleTertiary": null,
1136 + "description": "SHARON SMART Seascape IV, 2019 signed 'Smart '19' (lower right) pencil on paper framed: 22.5 cm. high x 26.5 cm. wide",
1137 + "url": "https://www.christies.com/en/sso?ObjectID=24637.59&LotNumber=59&ldp_breadcrumb=back",
1138 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0059_000(sharon_smart_seascape_iv_2019054830).jpg?mode=max",
1139 + "estimateLow": 100,
1140 + "estimateHigh": 200,
1141 + "estimateText": "GBP 100 - 200",
1142 + "priceRealised": null,
1143 + "priceRealisedText": null,
1144 + "startDate": "2026-08-20T00:00Z",
1145 + "endDate": "2026-09-02T23:00Z",
1146 + "withdrawn": false,
1147 + "isOver": true
1148 + },
1149 + {
1150 + "objectId": "6598300",
1151 + "lotNumber": "60",
1152 + "titlePrimary": "SHARON SMART",
1153 + "titleSecondary": "Seascape III, 2019",
1154 + "titleTertiary": null,
1155 + "description": "SHARON SMART Seascape III, 2019 signed 'Smart '19' (lower right) pencil on paper framed: 22.5 cm. high x 26.5 cm. wide",
1156 + "url": "https://www.christies.com/en/sso?ObjectID=24637.60&LotNumber=60&ldp_breadcrumb=back",
1157 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0060_000(sharon_smart_seascape_iii_2019054836).jpg?mode=max",
1158 + "estimateLow": 100,
1159 + "estimateHigh": 200,
1160 + "estimateText": "GBP 100 - 200",
1161 + "priceRealised": null,
1162 + "priceRealisedText": null,
1163 + "startDate": "2026-08-20T00:00Z",
1164 + "endDate": "2026-09-02T23:00Z",
1165 + "withdrawn": false,
1166 + "isOver": true
1167 + },
1168 + {
1169 + "objectId": "6598301",
1170 + "lotNumber": "61",
1171 + "titlePrimary": "KEVIN FRAZER",
1172 + "titleSecondary": "Combestone Tor, Dartmoor",
1173 + "titleTertiary": null,
1174 + "description": "KEVIN FRAZER Combestone Tor, Dartmoor hahnemühle fine art photographic 308 GSM print 61 cm. high x 46 cm. wide",
1175 + "url": "https://www.christies.com/en/sso?ObjectID=24637.61&LotNumber=61&ldp_breadcrumb=back",
1176 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0061_000(kevin_frazer_defenders_of_the_realm054843).jpg?mode=max",
1177 + "estimateLow": 200,
1178 + "estimateHigh": 300,
1179 + "estimateText": "GBP 200 - 300",
1180 + "priceRealised": null,
1181 + "priceRealisedText": null,
1182 + "startDate": "2026-08-20T00:00Z",
1183 + "endDate": "2026-09-02T23:00Z",
1184 + "withdrawn": false,
1185 + "isOver": true
1186 + },
1187 + {
1188 + "objectId": "6598302",
1189 + "lotNumber": "62",
1190 + "titlePrimary": "KEVIN FRAZER",
1191 + "titleSecondary": "Defenders of the Realm",
1192 + "titleTertiary": null,
1193 + "description": "KEVIN FRAZER Defenders of the Realm hahnemühle fine art photographic 308 GSM print 51 cm. high x 35.5 cm. wide",
1194 + "url": "https://www.christies.com/en/sso?ObjectID=24637.62&LotNumber=62&ldp_breadcrumb=back",
1195 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0062_000(kevin_frazer_combestone_tor_dartmoor054850).jpg?mode=max",
1196 + "estimateLow": 200,
1197 + "estimateHigh": 300,
1198 + "estimateText": "GBP 200 - 300",
1199 + "priceRealised": 127,
1200 + "priceRealisedText": "GBP 127",
1201 + "startDate": "2026-08-20T00:00Z",
1202 + "endDate": "2026-09-02T23:00Z",
1203 + "withdrawn": false,
1204 + "isOver": true
1205 + },
1206 + {
1207 + "objectId": "6598303",
1208 + "lotNumber": "63",
1209 + "titlePrimary": "KEVIN FRAZER",
1210 + "titleSecondary": "Synchro Pair",
1211 + "titleTertiary": null,
1212 + "description": "KEVIN FRAZER Synchro Pair hahnemühle fine art photographic 308 GSM print 46 cm. high x 30.5 cm. wide",
1213 + "url": "https://www.christies.com/en/sso?ObjectID=24637.63&LotNumber=63&ldp_breadcrumb=back",
1214 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0063_000(kevin_frazer_synchro_pair054855).jpg?mode=max",
1215 + "estimateLow": 100,
1216 + "estimateHigh": 200,
1217 + "estimateText": "GBP 100 - 200",
1218 + "priceRealised": 64,
1219 + "priceRealisedText": "GBP 64",
1220 + "startDate": "2026-08-20T00:00Z",
1221 + "endDate": "2026-09-02T23:00Z",
1222 + "withdrawn": false,
1223 + "isOver": true
1224 + },
1225 + {
1226 + "objectId": "6598304",
1227 + "lotNumber": "64",
1228 + "titlePrimary": "FERNANDO LOBINA",
1229 + "titleSecondary": "Iceland, 2022",
1230 + "titleTertiary": null,
1231 + "description": "FERNANDO LOBINA Iceland, 2022 photograpic print 22 cm. high x 30 cm. wide",
1232 + "url": "https://www.christies.com/en/sso?ObjectID=24637.64&LotNumber=64&ldp_breadcrumb=back",
1233 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0064_000(fernando_lobina_iceland_2022054901).jpg?mode=max",
1234 + "estimateLow": 100,
1235 + "estimateHigh": 200,
1236 + "estimateText": "GBP 100 - 200",
1237 + "priceRealised": 127,
1238 + "priceRealisedText": "GBP 127",
1239 + "startDate": "2026-08-20T00:00Z",
1240 + "endDate": "2026-09-02T23:00Z",
1241 + "withdrawn": false,
1242 + "isOver": true
1243 + },
1244 + {
1245 + "objectId": "6598305",
1246 + "lotNumber": "65",
1247 + "titlePrimary": "CAMILLA ELLINGSEN WEBSTER",
1248 + "titleSecondary": "Open, 2018",
1249 + "titleTertiary": null,
1250 + "description": "CAMILLA ELLINGSEN WEBSTER Open, 2018 signed 'A/P \"Open\" CW' photograph image: 12.7 cm. high x 12.7 cm. wide framed: 25.4 cm. high x 25.4 cm. wide",
1251 + "url": "https://www.christies.com/en/sso?ObjectID=24637.65&LotNumber=65&ldp_breadcrumb=back",
1252 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0065_000(camilla_ellingsen_webster_open_2018054907).jpg?mode=max",
1253 + "estimateLow": 100,
1254 + "estimateHigh": 200,
1255 + "estimateText": "GBP 100 - 200",
1256 + "priceRealised": 190,
1257 + "priceRealisedText": "GBP 190",
1258 + "startDate": "2026-08-20T00:00Z",
1259 + "endDate": "2026-09-02T23:00Z",
1260 + "withdrawn": false,
1261 + "isOver": true
1262 + },
1263 + {
1264 + "objectId": "6598306",
1265 + "lotNumber": "66",
1266 + "titlePrimary": "CAMILLA ELLINGSEN WEBSTER",
1267 + "titleSecondary": "Lolita, 2018",
1268 + "titleTertiary": null,
1269 + "description": "CAMILLA ELLINGSEN WEBSTER Lolita, 2018 signed 'A/P \"Lolita\"CW' (centre) photograph image: 25.4 cm. high × 25.4 cm. wide framed: 50.8 cm. high × 50.8 cm. wide",
1270 + "url": "https://www.christies.com/en/sso?ObjectID=24637.66&LotNumber=66&ldp_breadcrumb=back",
1271 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0066_000(camilla_ellingsen_webster_lolita_2018054914).jpg?mode=max",
1272 + "estimateLow": 200,
1273 + "estimateHigh": 300,
1274 + "estimateText": "GBP 200 - 300",
1275 + "priceRealised": 64,
1276 + "priceRealisedText": "GBP 64",
1277 + "startDate": "2026-08-20T00:00Z",
1278 + "endDate": "2026-09-02T23:00Z",
1279 + "withdrawn": false,
1280 + "isOver": true
1281 + },
1282 + {
1283 + "objectId": "6598307",
1284 + "lotNumber": "67",
1285 + "titlePrimary": "CAMILLA ELLINGSEN WEBSTER",
1286 + "titleSecondary": "Path, 2023",
1287 + "titleTertiary": null,
1288 + "description": "CAMILLA ELLINGSEN WEBSTER Path, 2023 signed 'A/P \"Path\" CW' (centre) photography 50.8 cm. high x 50.8 cm. wide",
1289 + "url": "https://www.christies.com/en/sso?ObjectID=24637.67&LotNumber=67&ldp_breadcrumb=back",
1290 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0067_000(camilla_ellingsen_webster_path_2023054921).jpg?mode=max",
1291 + "estimateLow": 200,
1292 + "estimateHigh": 300,
1293 + "estimateText": "GBP 200 - 300",
1294 + "priceRealised": null,
1295 + "priceRealisedText": null,
1296 + "startDate": "2026-08-20T00:00Z",
1297 + "endDate": "2026-09-02T23:00Z",
1298 + "withdrawn": false,
1299 + "isOver": true
1300 + },
1301 + {
1302 + "objectId": "6598308",
1303 + "lotNumber": "68",
1304 + "titlePrimary": "BENJAMIN SMITH",
1305 + "titleSecondary": "Glider",
1306 + "titleTertiary": null,
1307 + "description": "BENJAMIN SMITH Glider 35mm film on photo paper framed: 66 cm. high x 66 cm. wide",
1308 + "url": "https://www.christies.com/en/sso?ObjectID=24637.68&LotNumber=68&ldp_breadcrumb=back",
1309 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0068_000(benjamin_smith_glider054928).jpg?mode=max",
1310 + "estimateLow": 50,
1311 + "estimateHigh": 100,
1312 + "estimateText": "GBP 50 - 100",
1313 + "priceRealised": 190,
1314 + "priceRealisedText": "GBP 190",
1315 + "startDate": "2026-08-20T00:00Z",
1316 + "endDate": "2026-09-02T23:00Z",
1317 + "withdrawn": false,
1318 + "isOver": true
1319 + },
1320 + {
1321 + "objectId": "6598309",
1322 + "lotNumber": "69",
1323 + "titlePrimary": "BENJAMIN SMITH",
1324 + "titleSecondary": "Untitled #4",
1325 + "titleTertiary": null,
1326 + "description": "BENJAMIN SMITH Untitled #4 35mm film printed on rag paper framed: 56 cm. high x 42 cm. wide",
1327 + "url": "https://www.christies.com/en/sso?ObjectID=24637.69&LotNumber=69&ldp_breadcrumb=back",
1328 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0069_000(benjamin_smith_untitled_4054944).jpg?mode=max",
1329 + "estimateLow": 100,
1330 + "estimateHigh": 200,
1331 + "estimateText": "GBP 100 - 200",
1332 + "priceRealised": null,
1333 + "priceRealisedText": null,
1334 + "startDate": "2026-08-20T00:00Z",
1335 + "endDate": "2026-09-02T23:00Z",
1336 + "withdrawn": false,
1337 + "isOver": true
1338 + },
1339 + {
1340 + "objectId": "6598310",
1341 + "lotNumber": "70",
1342 + "titlePrimary": "BENJAMIN SMITH",
1343 + "titleSecondary": "Untitled #6",
1344 + "titleTertiary": null,
1345 + "description": "BENJAMIN SMITH Untitled #6 35mm film printed on rag paper framed: 56 cm. high x 42 cm. wide",
1346 + "url": "https://www.christies.com/en/sso?ObjectID=24637.70&LotNumber=70&ldp_breadcrumb=back",
1347 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0070_000(benjamin_smith_untitled_6054956).jpg?mode=max",
1348 + "estimateLow": 50,
1349 + "estimateHigh": 100,
1350 + "estimateText": "GBP 50 - 100",
1351 + "priceRealised": 64,
1352 + "priceRealisedText": "GBP 64",
1353 + "startDate": "2026-08-20T00:00Z",
1354 + "endDate": "2026-09-02T23:00Z",
1355 + "withdrawn": false,
1356 + "isOver": true
1357 + },
1358 + {
1359 + "objectId": "6598311",
1360 + "lotNumber": "71",
1361 + "titlePrimary": "ALBA RODRÍGUEZ",
1362 + "titleSecondary": "Rayo, 2026",
1363 + "titleTertiary": null,
1364 + "description": "ALBA RODRÍGUEZ Rayo, 2026 signed 'Rayo AlbaR'26' and numbered 1⁄10 in pencil photo etching 15 cm. high x 22.5 cm. wide",
1365 + "url": "https://www.christies.com/en/sso?ObjectID=24637.71&LotNumber=71&ldp_breadcrumb=back",
1366 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0071_000(alba_rodriguez_rayo_2026055007).jpg?mode=max",
1367 + "estimateLow": 100,
1368 + "estimateHigh": 200,
1369 + "estimateText": "GBP 100 - 200",
1370 + "priceRealised": null,
1371 + "priceRealisedText": null,
1372 + "startDate": "2026-08-20T00:00Z",
1373 + "endDate": "2026-09-02T23:00Z",
1374 + "withdrawn": false,
1375 + "isOver": true
1376 + },
1377 + {
1378 + "objectId": "6598312",
1379 + "lotNumber": "72",
1380 + "titlePrimary": "ALBA RODRÍGUEZ",
1381 + "titleSecondary": "Silhouettes, 2026",
1382 + "titleTertiary": null,
1383 + "description": "ALBA RODRÍGUEZ Silhouettes, 2026 signed 'Silhouettes AlbaR'26' and numbered edition 1⁄10 etching and aquatint 10 cm. high x 16 cm. wide",
1384 + "url": "https://www.christies.com/en/sso?ObjectID=24637.72&LotNumber=72&ldp_breadcrumb=back",
1385 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0072_000(alba_rodriguez_silhouettes_2026055013).jpg?mode=max",
1386 + "estimateLow": 100,
1387 + "estimateHigh": 200,
1388 + "estimateText": "GBP 100 - 200",
1389 + "priceRealised": 127,
1390 + "priceRealisedText": "GBP 127",
1391 + "startDate": "2026-08-20T00:00Z",
1392 + "endDate": "2026-09-02T23:00Z",
1393 + "withdrawn": false,
1394 + "isOver": true
1395 + },
1396 + {
1397 + "objectId": "6598313",
1398 + "lotNumber": "73",
1399 + "titlePrimary": "ALBA RODRIGUEZ",
1400 + "titleSecondary": "Tree house, 2026",
1401 + "titleTertiary": null,
1402 + "description": "ALBA RODRIGUEZ Tree house, 2026 signed 'Tree house AlbaR'26' and numbered edition 1⁄10 photo etching 22.5 cm. high x 15 cm. wide",
1403 + "url": "https://www.christies.com/en/sso?ObjectID=24637.73&LotNumber=73&ldp_breadcrumb=back",
1404 + "imageUrl": "https://www.christies.com/img/lotimages/2026/CKS/2026_CKS_24637_0073_000(alba_rodirguez_tree_house_2026055019).jpg?mode=max",
1405 + "estimateLow": 100,
1406 + "estimateHigh": 200,
1407 + "estimateText": "GBP 100 - 200",
1408 + "priceRealised": 127,
1409 + "priceRealisedText": "GBP 127",
1410 + "startDate": "2026-08-20T00:00Z",
1411 + "endDate": "2026-09-02T23:00Z",
1412 + "withdrawn": false,
1413 + "isOver": true
1414 + }
1415 + ]
1416 + },
1417 + "fetchedAt": "2026-09-07T06:06:26.771Z"
1418 + },
1419 + "expect": {
1420 + "minCount": 1,
1421 + "kinds": [
1422 + "sale"
1423 + ],
1424 + "first": {
1425 + "kind": "sale",
1426 + "auctionHouse": "Christie's",
1427 + "currency": "GBP"
1428 + }
1429 + },
1430 + "note": "Captured live by connectors/api/_auction-lib/smoke.ts on 2026-09-07 (44 records from this raw page).",
1431 + "capturedAt": "2026-09-07T06:06:26.781Z"
1432 +}
\ No newline at end of file
added data/fixtures/sothebys/closed-1.json +901 −0
@@ -0,0 +1,901 @@
1 +{
2 + "raw": {
3 + "url": "https://www.sothebys.com/en/buy/auction/2026/the-yang-zhendong-selection-kweichow-moutai-online",
4 + "externalId": "43cea93e-fa73-4f1c-ad3e-6991756da236#0",
5 + "kind": "sale",
6 + "engine": "api",
7 + "httpStatus": 200,
8 + "payload": {
9 + "kind": "auction_page",
10 + "auction": {
11 + "auctionId": "43cea93e-fa73-4f1c-ad3e-6991756da236",
12 + "url": "https://www.sothebys.com/en/buy/auction/2026/the-yang-zhendong-selection-kweichow-moutai-online",
13 + "title": "杨振东珍藏:贵州茅台网上专场 | The Yang Zhendong Selection: Kweichow Moutai Online",
14 + "saleNumber": "CN0041",
15 + "state": "Closed",
16 + "type": "Timed",
17 + "departments": [
18 + "Spirits"
19 + ],
20 + "currency": "CNY",
21 + "location": "Shanghai Auction",
22 + "startsAt": "2026-08-18T03:00Z",
23 + "endsAt": "2026-08-28T03:00Z",
24 + "closedAt": "2026-08-28T04:04:36.051959Z",
25 + "totalLots": 45
26 + },
27 + "offset": 0,
28 + "lots": [
29 + {
30 + "lotId": "38acbdee-4f1a-4e19-825a-70a8b1a0dfc1",
31 + "lotNumber": "1",
32 + "title": "2009年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2009 (6 x 500ml)",
33 + "creators": null,
34 + "slug": "2009nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
35 + "estimateLow": 17000,
36 + "estimateHigh": 22000,
37 + "isClosed": true,
38 + "closingTime": "2026-08-28T03:01Z",
39 + "currentBid": 17000,
40 + "bidCurrency": "CNY",
41 + "isSold": true,
42 + "finalPrice": 21250,
43 + "finalCurrency": "CNY",
44 + "numberOfBids": 1,
45 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/2c75bb0/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F95%2F59%2F403e61dc4148a8937220c637c28f%2F032-a.jpg",
46 + "withdrawn": false
47 + },
48 + {
49 + "lotId": "ed839d05-077b-4e24-a429-25c35311c52b",
50 + "lotNumber": "2",
51 + "title": "2009年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2009 (6 x 500ml)",
52 + "creators": null,
53 + "slug": "2009nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
54 + "estimateLow": 17000,
55 + "estimateHigh": 22000,
56 + "isClosed": true,
57 + "closingTime": "2026-08-28T03:02Z",
58 + "currentBid": 17000,
59 + "bidCurrency": "CNY",
60 + "isSold": true,
61 + "finalPrice": 21250,
62 + "finalCurrency": "CNY",
63 + "numberOfBids": 1,
64 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/994d926/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F0b%2F45%2F8b32668846a592410b00be27845e%2F033-a.jpg",
65 + "withdrawn": false
66 + },
67 + {
68 + "lotId": "38463946-6b73-4a5b-9710-cacfcbef485c",
69 + "lotNumber": "3",
70 + "title": "2008年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2008 (6 x 500ml)",
71 + "creators": null,
72 + "slug": "2008nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
73 + "estimateLow": 19000,
74 + "estimateHigh": 24000,
75 + "isClosed": true,
76 + "closingTime": "2026-08-28T03:03Z",
77 + "currentBid": 19000,
78 + "bidCurrency": "CNY",
79 + "isSold": true,
80 + "finalPrice": 23750,
81 + "finalCurrency": "CNY",
82 + "numberOfBids": 1,
83 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/17ed172/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F71%2F4f%2F426046b54799a040479faccae37a%2F029-a.jpg",
84 + "withdrawn": false
85 + },
86 + {
87 + "lotId": "be51ee7a-d6af-4237-a1f3-d3b36a62d92b",
88 + "lotNumber": "4",
89 + "title": "2008年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2008 (6 x 500ml)",
90 + "creators": null,
91 + "slug": "2008nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
92 + "estimateLow": 19000,
93 + "estimateHigh": 24000,
94 + "isClosed": true,
95 + "closingTime": "2026-08-28T03:04Z",
96 + "currentBid": 19000,
97 + "bidCurrency": "CNY",
98 + "isSold": true,
99 + "finalPrice": 23750,
100 + "finalCurrency": "CNY",
101 + "numberOfBids": 1,
102 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/95e42d4/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fdf%2F5c%2Fdc5808714722a1d4706f3c9f16af%2F030-a.jpg",
103 + "withdrawn": false
104 + },
105 + {
106 + "lotId": "818dcfcf-b8d9-4a51-a3fe-68a29d80a3dc",
107 + "lotNumber": "5",
108 + "title": "2007年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2007 (6 x 500ml)",
109 + "creators": null,
110 + "slug": "2007nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu",
111 + "estimateLow": 19000,
112 + "estimateHigh": 24000,
113 + "isClosed": true,
114 + "closingTime": "2026-08-28T03:05Z",
115 + "currentBid": 19000,
116 + "bidCurrency": "CNY",
117 + "isSold": true,
118 + "finalPrice": 23750,
119 + "finalCurrency": "CNY",
120 + "numberOfBids": 1,
121 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/b300d0f/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F63%2Fa1%2Fcd9b6737485987b4cd5a93414bfc%2F007-a.jpg",
122 + "withdrawn": false
123 + },
124 + {
125 + "lotId": "f6b7829b-54d9-47c0-929f-fe0a2afe8589",
126 + "lotNumber": "6",
127 + "title": "2007年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2007 (6 x 500ml)",
128 + "creators": null,
129 + "slug": "2007nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-2",
130 + "estimateLow": 19000,
131 + "estimateHigh": 24000,
132 + "isClosed": true,
133 + "closingTime": "2026-08-28T03:06Z",
134 + "currentBid": 19000,
135 + "bidCurrency": "CNY",
136 + "isSold": true,
137 + "finalPrice": 23750,
138 + "finalCurrency": "CNY",
139 + "numberOfBids": 1,
140 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/b6b4129/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F79%2Ff8%2Fc05f27f74d2eaab097070bb93310%2F008-a.jpg",
141 + "withdrawn": false
142 + },
143 + {
144 + "lotId": "9e899486-bda7-4c66-9b3f-9bec1f22182c",
145 + "lotNumber": "7",
146 + "title": "2007年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2007 (6 x 500ml)",
147 + "creators": null,
148 + "slug": "2007nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
149 + "estimateLow": 19000,
150 + "estimateHigh": 24000,
151 + "isClosed": true,
152 + "closingTime": "2026-08-28T03:07Z",
153 + "currentBid": 19000,
154 + "bidCurrency": "CNY",
155 + "isSold": true,
156 + "finalPrice": 23750,
157 + "finalCurrency": "CNY",
158 + "numberOfBids": 1,
159 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/2d2624c/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fd1%2Ffd%2Fdcfb566c45f499c098f0b7e26c1b%2F011-a.jpg",
160 + "withdrawn": false
161 + },
162 + {
163 + "lotId": "47149e65-83e0-496e-a95f-b88b503f85b4",
164 + "lotNumber": "8",
165 + "title": "2007年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2007 (6 x 500ml)",
166 + "creators": null,
167 + "slug": "2007nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
168 + "estimateLow": 19000,
169 + "estimateHigh": 24000,
170 + "isClosed": true,
171 + "closingTime": "2026-08-28T03:08Z",
172 + "currentBid": 19000,
173 + "bidCurrency": "CNY",
174 + "isSold": true,
175 + "finalPrice": 23750,
176 + "finalCurrency": "CNY",
177 + "numberOfBids": 1,
178 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/9d03c31/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F09%2Fab%2F33ac8ccd4f90ba051f6a82f21935%2F025-a.jpg",
179 + "withdrawn": false
180 + },
181 + {
182 + "lotId": "fdbee854-9733-45d9-ac6a-6a3795aa1d03",
183 + "lotNumber": "9",
184 + "title": "2006年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2006 (6 x 500ml)",
185 + "creators": null,
186 + "slug": "2006nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu",
187 + "estimateLow": 20000,
188 + "estimateHigh": 26000,
189 + "isClosed": true,
190 + "closingTime": "2026-08-28T03:09Z",
191 + "currentBid": 20000,
192 + "bidCurrency": "CNY",
193 + "isSold": true,
194 + "finalPrice": 25000,
195 + "finalCurrency": "CNY",
196 + "numberOfBids": 1,
197 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/2fe1026/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F11%2Faf%2Fd5f5a3e94f5abfa41b3ace0ed0d9%2F013-a.jpg",
198 + "withdrawn": false
199 + },
200 + {
201 + "lotId": "d3d70cb7-eec1-4f75-b68d-c71482a4dcff",
202 + "lotNumber": "10",
203 + "title": "2006年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2006 (6 x 500ml)",
204 + "creators": null,
205 + "slug": "2006nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-2",
206 + "estimateLow": 20000,
207 + "estimateHigh": 26000,
208 + "isClosed": true,
209 + "closingTime": "2026-08-28T03:10Z",
210 + "currentBid": 20000,
211 + "bidCurrency": "CNY",
212 + "isSold": true,
213 + "finalPrice": 25000,
214 + "finalCurrency": "CNY",
215 + "numberOfBids": 1,
216 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/05952bf/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F39%2F16%2F7946198c4322a1568cca7a81a911%2F014-a.jpg",
217 + "withdrawn": false
218 + },
219 + {
220 + "lotId": "25aaeb3d-79fa-4cc6-a36a-4bb38a84df65",
221 + "lotNumber": "11",
222 + "title": "2004年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2004 (6 x 500ml)",
223 + "creators": null,
224 + "slug": "2004nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu",
225 + "estimateLow": 20000,
226 + "estimateHigh": 26000,
227 + "isClosed": true,
228 + "closingTime": "2026-08-28T03:11Z",
229 + "currentBid": 20000,
230 + "bidCurrency": "CNY",
231 + "isSold": true,
232 + "finalPrice": 25000,
233 + "finalCurrency": "CNY",
234 + "numberOfBids": 1,
235 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/487c678/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F62%2Fc8%2F9b80241649918a070b1994881a08%2F022-a.jpg",
236 + "withdrawn": false
237 + },
238 + {
239 + "lotId": "1882d5e4-335e-4159-8a2f-d073b1478fd4",
240 + "lotNumber": "12",
241 + "title": "2004年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2004 (6 x 500ml)",
242 + "creators": null,
243 + "slug": "2004nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-2",
244 + "estimateLow": 20000,
245 + "estimateHigh": 26000,
246 + "isClosed": true,
247 + "closingTime": "2026-08-28T03:12Z",
248 + "currentBid": 20000,
249 + "bidCurrency": "CNY",
250 + "isSold": true,
251 + "finalPrice": 25000,
252 + "finalCurrency": "CNY",
253 + "numberOfBids": 1,
254 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/1cc1d2e/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F5e%2F51%2F28898452468387ec72c3ce6a5157%2F028-a.jpg",
255 + "withdrawn": false
256 + },
257 + {
258 + "lotId": "423e2021-f6d7-429a-8c4f-7ebb77c67f14",
259 + "lotNumber": "13",
260 + "title": "2004年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2004 (6 x 500ml)",
261 + "creators": null,
262 + "slug": "2004nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
263 + "estimateLow": 20000,
264 + "estimateHigh": 26000,
265 + "isClosed": true,
266 + "closingTime": "2026-08-28T03:14:57.173666Z",
267 + "currentBid": 22000,
268 + "bidCurrency": "CNY",
269 + "isSold": true,
270 + "finalPrice": 27500,
271 + "finalCurrency": "CNY",
272 + "numberOfBids": 2,
273 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/e8a4d9e/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F5f%2Fbb%2Fe93ffb79479ca3f63adc4590bffe%2F012-a.jpg",
274 + "withdrawn": false
275 + },
276 + {
277 + "lotId": "cfceb1e2-951a-484b-97f7-50f69446869f",
278 + "lotNumber": "14",
279 + "title": "2004年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2004 (6 x 500ml)",
280 + "creators": null,
281 + "slug": "2004nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
282 + "estimateLow": 20000,
283 + "estimateHigh": 26000,
284 + "isClosed": true,
285 + "closingTime": "2026-08-28T03:14Z",
286 + "currentBid": 22000,
287 + "bidCurrency": "CNY",
288 + "isSold": true,
289 + "finalPrice": 27500,
290 + "finalCurrency": "CNY",
291 + "numberOfBids": 2,
292 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/9479dcb/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F71%2F4c%2Fabd090fc4257b157c35565a347f9%2F027-a.jpg",
293 + "withdrawn": false
294 + },
295 + {
296 + "lotId": "a8d4cbbd-925a-4a4e-8b82-7203446a5eb9",
297 + "lotNumber": "15",
298 + "title": "2003年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2003 (6 x 500ml)",
299 + "creators": null,
300 + "slug": "2003nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu",
301 + "estimateLow": 22000,
302 + "estimateHigh": 30000,
303 + "isClosed": true,
304 + "closingTime": "2026-08-28T03:15Z",
305 + "currentBid": 22000,
306 + "bidCurrency": "CNY",
307 + "isSold": true,
308 + "finalPrice": 27500,
309 + "finalCurrency": "CNY",
310 + "numberOfBids": 1,
311 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/688dee7/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F66%2F36%2Fa0e6c9dd45dd843b1ef7bbccb428%2F015-a.jpg",
312 + "withdrawn": false
313 + },
314 + {
315 + "lotId": "61e1e0e3-2a7b-411f-8acd-918d54e9c318",
316 + "lotNumber": "16",
317 + "title": "2003年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2003 (6 x 500ml)",
318 + "creators": null,
319 + "slug": "2003nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-2",
320 + "estimateLow": 22000,
321 + "estimateHigh": 30000,
322 + "isClosed": true,
323 + "closingTime": "2026-08-28T03:16Z",
324 + "currentBid": 22000,
325 + "bidCurrency": "CNY",
326 + "isSold": true,
327 + "finalPrice": 27500,
328 + "finalCurrency": "CNY",
329 + "numberOfBids": 1,
330 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/d1874bc/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F03%2Fbb%2Faaa11b56470fbf081d3f30069032%2F016-a.jpg",
331 + "withdrawn": false
332 + },
333 + {
334 + "lotId": "c0239655-9ccc-4173-a42e-d514984345a0",
335 + "lotNumber": "17",
336 + "title": "2003年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2003 (6 x 500ml)",
337 + "creators": null,
338 + "slug": "2003nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
339 + "estimateLow": 22000,
340 + "estimateHigh": 30000,
341 + "isClosed": true,
342 + "closingTime": "2026-08-28T03:17Z",
343 + "currentBid": 22000,
344 + "bidCurrency": "CNY",
345 + "isSold": true,
346 + "finalPrice": 27500,
347 + "finalCurrency": "CNY",
348 + "numberOfBids": 1,
349 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/e9fa076/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F40%2F95%2F80d62649485cb8e1b427d93b5ea9%2F024-a.jpg",
350 + "withdrawn": false
351 + },
352 + {
353 + "lotId": "461f3b9c-bd4b-4dac-a4a0-dae79fe5ae5c",
354 + "lotNumber": "18",
355 + "title": "2003年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2003 (6 x 500ml)",
356 + "creators": null,
357 + "slug": "2003nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
358 + "estimateLow": 22000,
359 + "estimateHigh": 30000,
360 + "isClosed": true,
361 + "closingTime": "2026-08-28T03:18Z",
362 + "currentBid": 22000,
363 + "bidCurrency": "CNY",
364 + "isSold": true,
365 + "finalPrice": 27500,
366 + "finalCurrency": "CNY",
367 + "numberOfBids": 1,
368 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/9663ded/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fd6%2Fc8%2Fa3901b724616ac86f6817889b03a%2F026-a.jpg",
369 + "withdrawn": false
370 + },
371 + {
372 + "lotId": "eee31fed-1b85-4085-bdeb-341847f5edb1",
373 + "lotNumber": "19",
374 + "title": "2002年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2002 (6 x 500ml)",
375 + "creators": null,
376 + "slug": "2002nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu",
377 + "estimateLow": 24000,
378 + "estimateHigh": 32000,
379 + "isClosed": true,
380 + "closingTime": "2026-08-28T03:19Z",
381 + "currentBid": 24000,
382 + "bidCurrency": "CNY",
383 + "isSold": true,
384 + "finalPrice": 30000,
385 + "finalCurrency": "CNY",
386 + "numberOfBids": 1,
387 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/b3d8b5d/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fc5%2F55%2Fd2e7368444e0b771fcf6b3b7a216%2F009-a.jpg",
388 + "withdrawn": false
389 + },
390 + {
391 + "lotId": "26bc6348-4085-488b-914b-832ed154b6f3",
392 + "lotNumber": "20",
393 + "title": "2002年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2002 (6 x 500ml)",
394 + "creators": null,
395 + "slug": "2002nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-2",
396 + "estimateLow": 24000,
397 + "estimateHigh": 32000,
398 + "isClosed": true,
399 + "closingTime": "2026-08-28T03:20Z",
400 + "currentBid": 24000,
401 + "bidCurrency": "CNY",
402 + "isSold": true,
403 + "finalPrice": 30000,
404 + "finalCurrency": "CNY",
405 + "numberOfBids": 1,
406 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/1b1076a/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F35%2F6d%2F2409b7764ba5800be392241e48ab%2F010-a.jpg",
407 + "withdrawn": false
408 + },
409 + {
410 + "lotId": "ed4de8e9-11f1-4721-9c53-5309930ac924",
411 + "lotNumber": "21",
412 + "title": "2002年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2002 (6 x 500ml)",
413 + "creators": null,
414 + "slug": "2002nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
415 + "estimateLow": 24000,
416 + "estimateHigh": 32000,
417 + "isClosed": true,
418 + "closingTime": "2026-08-28T03:21Z",
419 + "currentBid": 24000,
420 + "bidCurrency": "CNY",
421 + "isSold": true,
422 + "finalPrice": 30000,
423 + "finalCurrency": "CNY",
424 + "numberOfBids": 1,
425 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/e4fe475/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F13%2Fd5%2F869681d34781bc67424c58b35b00%2F020-a.jpg",
426 + "withdrawn": false
427 + },
428 + {
429 + "lotId": "c9b88183-ff36-4d70-afc7-6393dd1d238c",
430 + "lotNumber": "22",
431 + "title": "2002年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2002 (6 x 500ml)",
432 + "creators": null,
433 + "slug": "2002nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
434 + "estimateLow": 24000,
435 + "estimateHigh": 32000,
436 + "isClosed": true,
437 + "closingTime": "2026-08-28T03:22Z",
438 + "currentBid": 24000,
439 + "bidCurrency": "CNY",
440 + "isSold": true,
441 + "finalPrice": 30000,
442 + "finalCurrency": "CNY",
443 + "numberOfBids": 1,
444 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/3312497/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fc2%2F10%2Fea1df9f14c8b8690f99af80bc8a8%2F021-a.jpg",
445 + "withdrawn": false
446 + },
447 + {
448 + "lotId": "5ac4dc52-f406-45d5-b760-e0b6bcf1f290",
449 + "lotNumber": "23",
450 + "title": "2001年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2001 (6 x 500ml)",
451 + "creators": null,
452 + "slug": "2001nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu",
453 + "estimateLow": 24000,
454 + "estimateHigh": 35000,
455 + "isClosed": true,
456 + "closingTime": "2026-08-28T03:23Z",
457 + "currentBid": 24000,
458 + "bidCurrency": "CNY",
459 + "isSold": true,
460 + "finalPrice": 30000,
461 + "finalCurrency": "CNY",
462 + "numberOfBids": 1,
463 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/5f2cba9/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F06%2Ff8%2Fc96367e149b7b632f058108767ab%2F005-a.jpg",
464 + "withdrawn": false
465 + },
466 + {
467 + "lotId": "9e88d951-3a6e-43e9-b8a2-0e63a8ed7dee",
468 + "lotNumber": "24",
469 + "title": "2001年产 “五星牌”贵州茅台酒 Kweichow Five Star Moutai 2001 (6 x 500ml)",
470 + "creators": null,
471 + "slug": "2001nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-2",
472 + "estimateLow": 24000,
473 + "estimateHigh": 35000,
474 + "isClosed": true,
475 + "closingTime": "2026-08-28T03:24Z",
476 + "currentBid": 24000,
477 + "bidCurrency": "CNY",
478 + "isSold": true,
479 + "finalPrice": 30000,
480 + "finalCurrency": "CNY",
481 + "numberOfBids": 1,
482 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/b559bfa/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fad%2F79%2Fbc00b0a246af91fc810dbf4c823a%2F023-a.jpg",
483 + "withdrawn": false
484 + },
485 + {
486 + "lotId": "ba3fb029-998a-43d2-b4b4-ababb35001f9",
487 + "lotNumber": "25",
488 + "title": "2001年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2001 (6 x 500ml)",
489 + "creators": null,
490 + "slug": "2001nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
491 + "estimateLow": 24000,
492 + "estimateHigh": 35000,
493 + "isClosed": true,
494 + "closingTime": "2026-08-28T03:25Z",
495 + "currentBid": 24000,
496 + "bidCurrency": "CNY",
497 + "isSold": true,
498 + "finalPrice": 30000,
499 + "finalCurrency": "CNY",
500 + "numberOfBids": 1,
501 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/31cd061/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fb7%2F68%2F82d4008b4ae79f2490f555e1f0cc%2F017-a.jpg",
502 + "withdrawn": false
503 + },
504 + {
505 + "lotId": "cba61b07-b388-49ca-bd8f-5a7d2db97c6b",
506 + "lotNumber": "26",
507 + "title": "2001年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 2001 (6 x 500ml)",
508 + "creators": null,
509 + "slug": "2001nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
510 + "estimateLow": 24000,
511 + "estimateHigh": 35000,
512 + "isClosed": true,
513 + "closingTime": "2026-08-28T03:26Z",
514 + "currentBid": 24000,
515 + "bidCurrency": "CNY",
516 + "isSold": true,
517 + "finalPrice": 30000,
518 + "finalCurrency": "CNY",
519 + "numberOfBids": 1,
520 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/1fdc890/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fa2%2F79%2F546d2cba488587afa0ace93978cc%2F018-a.jpg",
521 + "withdrawn": false
522 + },
523 + {
524 + "lotId": "43bff431-c2f7-4e83-9390-fc5fcd6f45b0",
525 + "lotNumber": "27",
526 + "title": "2000年产 “五星牌”贵州茅台酒 (太阳标) Kweichow Five Star Moutai 2000 (White sticker) (6 x 500ml)",
527 + "creators": null,
528 + "slug": "2000nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-tai",
529 + "estimateLow": 28000,
530 + "estimateHigh": 38000,
531 + "isClosed": true,
532 + "closingTime": "2026-08-28T03:27Z",
533 + "currentBid": 28000,
534 + "bidCurrency": "CNY",
535 + "isSold": true,
536 + "finalPrice": 35000,
537 + "finalCurrency": "CNY",
538 + "numberOfBids": 1,
539 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/8acd881/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F2c%2Fda%2F91c4d2264263a18d5f6a4abe4e4b%2F003-a.jpg",
540 + "withdrawn": false
541 + },
542 + {
543 + "lotId": "c1f62e53-7a65-479b-b5a3-7c8501f02f38",
544 + "lotNumber": "28",
545 + "title": "2000年产 “五星牌”贵州茅台酒 (太阳标) Kweichow Five Star Moutai 2000 (White sticker) (6 x 500ml)",
546 + "creators": null,
547 + "slug": "2000nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-tai-2",
548 + "estimateLow": 28000,
549 + "estimateHigh": 38000,
550 + "isClosed": true,
551 + "closingTime": "2026-08-28T03:28Z",
552 + "currentBid": 28000,
553 + "bidCurrency": "CNY",
554 + "isSold": true,
555 + "finalPrice": 35000,
556 + "finalCurrency": "CNY",
557 + "numberOfBids": 1,
558 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/ab41aae/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F33%2F0d%2F24b346844fd295e9591452dbd939%2F037-a.jpg",
559 + "withdrawn": false
560 + },
561 + {
562 + "lotId": "0954435f-be25-435b-aad4-f8de96d81d05",
563 + "lotNumber": "29",
564 + "title": "2000年产 “飞天牌”贵州茅台酒 (太阳标) Kweichow Flying Fairy Moutai 2000 (White sticker) (6 x 500ml)",
565 + "creators": null,
566 + "slug": "2000nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
567 + "estimateLow": 28000,
568 + "estimateHigh": 38000,
569 + "isClosed": true,
570 + "closingTime": "2026-08-28T03:29Z",
571 + "currentBid": 28000,
572 + "bidCurrency": "CNY",
573 + "isSold": true,
574 + "finalPrice": 35000,
575 + "finalCurrency": "CNY",
576 + "numberOfBids": 1,
577 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/5157b9a/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F18%2Fc4%2F9c5f6e5a4e0ab19baee44778a90a%2F004-a.jpg",
578 + "withdrawn": false
579 + },
580 + {
581 + "lotId": "f32c44b3-c778-479a-8f52-c04ec867dc14",
582 + "lotNumber": "30",
583 + "title": "2000年产 “飞天牌”贵州茅台酒 (太阳标) Kweichow Flying Fairy Moutai 2000 (White sticker) (6 x 500ml)",
584 + "creators": null,
585 + "slug": "2000nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
586 + "estimateLow": 28000,
587 + "estimateHigh": 38000,
588 + "isClosed": true,
589 + "closingTime": "2026-08-28T03:30Z",
590 + "currentBid": 28000,
591 + "bidCurrency": "CNY",
592 + "isSold": true,
593 + "finalPrice": 35000,
594 + "finalCurrency": "CNY",
595 + "numberOfBids": 1,
596 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/8c4dab1/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F6d%2Fac%2F5c2cdc484346813a467cf2644136%2F042-a.jpg",
597 + "withdrawn": false
598 + },
599 + {
600 + "lotId": "0bb90acf-44e8-43ee-b5db-2f9e2f97fc2c",
601 + "lotNumber": "31",
602 + "title": "2000年产 “五星牌”贵州茅台酒 (蓝标) Kweichow Five Star Moutai 2000 (Blue sticker) (6 x 500ml)",
603 + "creators": null,
604 + "slug": "2000nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-lan",
605 + "estimateLow": 28000,
606 + "estimateHigh": 38000,
607 + "isClosed": true,
608 + "closingTime": "2026-08-28T03:31Z",
609 + "currentBid": 28000,
610 + "bidCurrency": "CNY",
611 + "isSold": true,
612 + "finalPrice": 35000,
613 + "finalCurrency": "CNY",
614 + "numberOfBids": 1,
615 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/335b202/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F81%2F18%2F2c9d68564a3c923c899be61e9df4%2F035-a.jpg",
616 + "withdrawn": false
617 + },
618 + {
619 + "lotId": "b83c1afa-5236-486a-8893-47368254d6f8",
620 + "lotNumber": "32",
621 + "title": "2000年产 “五星牌”贵州茅台酒 (蓝标) Kweichow Five Star Moutai 2000 (Blue sticker) (6 x 500ml)",
622 + "creators": null,
623 + "slug": "2000nian-chan-wu-xing-pai-gui-zhou-mao-tai-jiu-lan-2",
624 + "estimateLow": 28000,
625 + "estimateHigh": 38000,
626 + "isClosed": true,
627 + "closingTime": "2026-08-28T03:32Z",
628 + "currentBid": 32000,
629 + "bidCurrency": "CNY",
630 + "isSold": true,
631 + "finalPrice": 40000,
632 + "finalCurrency": "CNY",
633 + "numberOfBids": 3,
634 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/028b6f4/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F8f%2F9b%2F0091e03f4209be648545ea055037%2F036-a.jpg",
635 + "withdrawn": false
636 + },
637 + {
638 + "lotId": "b857c260-6e82-4525-8525-14d4c18dad24",
639 + "lotNumber": "33",
640 + "title": "2000年产 “飞天牌”贵州茅台酒 (蓝标) Kweichow Flying Fairy Moutai 2000 (Blue sticker) (6 x 500ml)",
641 + "creators": null,
642 + "slug": "2000nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-3",
643 + "estimateLow": 28000,
644 + "estimateHigh": 38000,
645 + "isClosed": true,
646 + "closingTime": "2026-08-28T03:33Z",
647 + "currentBid": 30000,
648 + "bidCurrency": "CNY",
649 + "isSold": true,
650 + "finalPrice": 37500,
651 + "finalCurrency": "CNY",
652 + "numberOfBids": 2,
653 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/86968e7/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Ffa%2Fe4%2Fccd4fdee46a180defa48050af80d%2F002-a.jpg",
654 + "withdrawn": false
655 + },
656 + {
657 + "lotId": "3cd7b277-244a-44be-a6a3-612f80187305",
658 + "lotNumber": "34",
659 + "title": " 2000年产 “飞天牌”贵州茅台酒 (蓝标) Kweichow Flying Fairy Moutai 2000 (Blue sticker) (6 x 500ml)",
660 + "creators": null,
661 + "slug": "2000nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-4",
662 + "estimateLow": 28000,
663 + "estimateHigh": 38000,
664 + "isClosed": true,
665 + "closingTime": "2026-08-28T03:34Z",
666 + "currentBid": 28000,
667 + "bidCurrency": "CNY",
668 + "isSold": true,
669 + "finalPrice": 35000,
670 + "finalCurrency": "CNY",
671 + "numberOfBids": 1,
672 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/9ebf750/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F91%2F2b%2F96ec2ebe4b67a809b629c7553eeb%2F006-a.jpg",
673 + "withdrawn": false
674 + },
675 + {
676 + "lotId": "f15473a1-c8a1-4e0d-839a-d63550a653ab",
677 + "lotNumber": "35",
678 + "title": "1994年产 “飞天牌”贵州茅台酒 (铁盖) Kweichow Flying Fairy Moutai 1994 (Iron Capsule) (6 x 375ml)",
679 + "creators": null,
680 + "slug": "1994nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
681 + "estimateLow": 40000,
682 + "estimateHigh": 55000,
683 + "isClosed": true,
684 + "closingTime": "2026-08-28T03:35Z",
685 + "currentBid": 40000,
686 + "bidCurrency": "CNY",
687 + "isSold": true,
688 + "finalPrice": 50000,
689 + "finalCurrency": "CNY",
690 + "numberOfBids": 1,
691 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/ceb6399/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F4f%2F21%2F395a3752442d9916bc9715184c59%2F038-a.jpg",
692 + "withdrawn": false
693 + },
694 + {
695 + "lotId": "5e6e55ee-1e5d-415d-b46a-848c92505b52",
696 + "lotNumber": "36",
697 + "title": "1993年产 “飞天牌”贵州茅台酒 (铁盖) Kweichow Flying Fairy Moutai 1993 (Iron Capsule) (6 x 375ml)",
698 + "creators": null,
699 + "slug": "1993nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
700 + "estimateLow": 40000,
701 + "estimateHigh": 55000,
702 + "isClosed": true,
703 + "closingTime": "2026-08-28T03:36Z",
704 + "currentBid": 70000,
705 + "bidCurrency": "CNY",
706 + "isSold": true,
707 + "finalPrice": 87500,
708 + "finalCurrency": "CNY",
709 + "numberOfBids": 9,
710 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/4e3f39d/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fbe%2Fa3%2F111f9f964e6ca62a45f8f4047f8f%2F039-a.jpg",
711 + "withdrawn": false
712 + },
713 + {
714 + "lotId": "1c747026-6524-42cc-b025-5baa03a0ab9a",
715 + "lotNumber": "37",
716 + "title": "1992年产 “飞天牌”贵州茅台酒 (铁盖) Kweichow Flying Fairy Moutai 1992 (Iron Capsule) (6 x 200ml)",
717 + "creators": null,
718 + "slug": "1992nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
719 + "estimateLow": 22000,
720 + "estimateHigh": 28000,
721 + "isClosed": true,
722 + "closingTime": "2026-08-28T03:37Z",
723 + "currentBid": 28000,
724 + "bidCurrency": "CNY",
725 + "isSold": true,
726 + "finalPrice": 35000,
727 + "finalCurrency": "CNY",
728 + "numberOfBids": 4,
729 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/a5f7a09/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F2e%2F70%2F60d808e44737aaadf1f29d46af9b%2F034-a.jpg",
730 + "withdrawn": false
731 + },
732 + {
733 + "lotId": "3bb3f155-fa26-4159-9ebf-e240537a7139",
734 + "lotNumber": "38",
735 + "title": "1992年产 “飞天牌”贵州茅台酒 (铁盖) Kweichow Flying Fairy Moutai 1992 (Iron Capsule) (6 x 375ml)",
736 + "creators": null,
737 + "slug": "1992nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
738 + "estimateLow": 40000,
739 + "estimateHigh": 55000,
740 + "isClosed": true,
741 + "closingTime": "2026-08-28T03:38Z",
742 + "currentBid": 40000,
743 + "bidCurrency": "CNY",
744 + "isSold": true,
745 + "finalPrice": 50000,
746 + "finalCurrency": "CNY",
747 + "numberOfBids": 1,
748 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/e28bc84/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F81%2F18%2F2e44c0a346c784d530ee9d06ede7%2F040-a.jpg",
749 + "withdrawn": false
750 + },
751 + {
752 + "lotId": "f6d13ac8-b6c6-4d81-be52-c892fb9a4dd9",
753 + "lotNumber": "39",
754 + "title": "1991年产 “飞天牌”贵州茅台酒 (铁盖) Kweichow Flying Fairy Moutai 1991 (Iron Capsule) (6 x 200ml)",
755 + "creators": null,
756 + "slug": "1991nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
757 + "estimateLow": 22000,
758 + "estimateHigh": 28000,
759 + "isClosed": true,
760 + "closingTime": "2026-08-28T03:39Z",
761 + "currentBid": 24000,
762 + "bidCurrency": "CNY",
763 + "isSold": true,
764 + "finalPrice": 30000,
765 + "finalCurrency": "CNY",
766 + "numberOfBids": 2,
767 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/e4ab47d/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F3b%2Fc2%2Fef6c7105427a996bc0cc9b36ef69%2F001-a.jpg",
768 + "withdrawn": false
769 + },
770 + {
771 + "lotId": "ba1855b8-0a84-4219-bd9f-e181cc415c99",
772 + "lotNumber": "40",
773 + "title": "1991年产 “飞天牌”贵州茅台酒 (铁盖) Kweichow Flying Fairy Moutai 1991 (Iron Capsule) (6 x 375ml)",
774 + "creators": null,
775 + "slug": "1991nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu-2",
776 + "estimateLow": 40000,
777 + "estimateHigh": 55000,
778 + "isClosed": true,
779 + "closingTime": "2026-08-28T03:40Z",
780 + "currentBid": 42000,
781 + "bidCurrency": "CNY",
782 + "isSold": true,
783 + "finalPrice": 52500,
784 + "finalCurrency": "CNY",
785 + "numberOfBids": 2,
786 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/3d95b57/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fc3%2F1b%2Fd662b03d469eb6283009728a34fb%2F041-a.jpg",
787 + "withdrawn": false
788 + },
789 + {
790 + "lotId": "8f71e958-c98b-4c96-b20d-b4fd872ba082",
791 + "lotNumber": "41",
792 + "title": "1985年产 “飞天牌”贵州茅台酒 Kweichow Flying Fairy Moutai 1985 (3 x 500ml)",
793 + "creators": null,
794 + "slug": "1985nian-chan-fei-tian-pai-gui-zhou-mao-tai-jiu",
795 + "estimateLow": 50000,
796 + "estimateHigh": 70000,
797 + "isClosed": true,
798 + "closingTime": "2026-08-28T03:41Z",
799 + "currentBid": 50000,
800 + "bidCurrency": "CNY",
801 + "isSold": true,
802 + "finalPrice": 62500,
803 + "finalCurrency": "CNY",
804 + "numberOfBids": 1,
805 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/5b2d8a4/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F5c%2F1c%2F9a0cde90476d889b8d7b629b82cf%2F031-a.jpg",
806 + "withdrawn": false
807 + },
808 + {
809 + "lotId": "667504c2-773b-4caf-b939-a9eacf631e4d",
810 + "lotNumber": "42",
811 + "title": "1983-1985年产 “大飞天”贵州茅台酒 Kweichow Flying Fairy Moutai circa 1983-1985 (3 x 540ml)",
812 + "creators": null,
813 + "slug": "1983-1985nian-chan-da-fei-tian-gui-zhou-mao-tai",
814 + "estimateLow": 50000,
815 + "estimateHigh": 70000,
816 + "isClosed": true,
817 + "closingTime": "2026-08-28T03:42Z",
818 + "currentBid": 50000,
819 + "bidCurrency": "CNY",
820 + "isSold": true,
821 + "finalPrice": 62500,
822 + "finalCurrency": "CNY",
823 + "numberOfBids": 1,
824 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/f7514a9/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F07%2F4a%2Ff37c0e324b26b5501ec5fe9163db%2F019-a.jpg",
825 + "withdrawn": false
826 + },
827 + {
828 + "lotId": "21d3b025-978d-4537-a760-180b0ac0cf04",
829 + "lotNumber": "43",
830 + "title": "2000年产 “飞天牌”珍品贵州茅台酒 (太阳标) Kweichow Flying Fairy Precious Moutai 2000 (White sticker) (12 x 500ml)",
831 + "creators": null,
832 + "slug": "2000nian-chan-fei-tian-pai-zhen-pin-gui-zhou-mao",
833 + "estimateLow": 70000,
834 + "estimateHigh": 95000,
835 + "isClosed": true,
836 + "closingTime": "2026-08-28T03:43Z",
837 + "currentBid": 75000,
838 + "bidCurrency": "CNY",
839 + "isSold": true,
840 + "finalPrice": 93750,
841 + "finalCurrency": "CNY",
842 + "numberOfBids": 2,
843 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/4a51929/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F4a%2F70%2Fc2585a884cdb9c678c32643bc89d%2F043-a.jpg",
844 + "withdrawn": false
845 + },
846 + {
847 + "lotId": "b30b447c-f872-4a58-bf56-ad9959d37fbf",
848 + "lotNumber": "44",
849 + "title": "1997年产 “飞天牌”珍品贵州茅台酒 Kweichow Flying Fairy Precious Moutai 1997 (12 x 500ml)",
850 + "creators": null,
851 + "slug": "1997nian-chan-fei-tian-pai-zhen-pin-gui-zhou-mao",
852 + "estimateLow": 85000,
853 + "estimateHigh": 120000,
854 + "isClosed": true,
855 + "closingTime": "2026-08-28T03:45:58.039480Z",
856 + "currentBid": 110000,
857 + "bidCurrency": "CNY",
858 + "isSold": true,
859 + "finalPrice": 137500,
860 + "finalCurrency": "CNY",
861 + "numberOfBids": 6,
862 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/709363e/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Ff1%2F19%2F693696504232843e0efa6dade421%2F045-a.jpg",
863 + "withdrawn": false
864 + },
865 + {
866 + "lotId": "2c2a1eac-6bd9-4fb5-ad67-ef183992a725",
867 + "lotNumber": "45",
868 + "title": "1998年产 “飞天牌”珍品贵州茅台酒 Kweichow Flying Fairy Precious Moutai 1998 (12 x 500ml)",
869 + "creators": null,
870 + "slug": "1998nian-chan-fei-tian-pai-zhen-pin-gui-zhou-mao",
871 + "estimateLow": 80000,
872 + "estimateHigh": 120000,
873 + "isClosed": true,
874 + "closingTime": "2026-08-28T03:46:08.398471Z",
875 + "currentBid": 90000,
876 + "bidCurrency": "CNY",
877 + "isSold": true,
878 + "finalPrice": 112500,
879 + "finalCurrency": "CNY",
880 + "numberOfBids": 3,
881 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/1812306/2147483647/strip/true/crop/2000x1778+0+0/resize/4096x3641!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fcb%2F98%2F7771d8c54e4bbef139f925a8c487%2F044-a.jpg",
882 + "withdrawn": false
883 + }
884 + ]
885 + },
886 + "fetchedAt": "2026-09-07T06:06:54.265Z"
887 + },
888 + "expect": {
889 + "minCount": 1,
890 + "kinds": [
891 + "sale"
892 + ],
893 + "first": {
894 + "kind": "sale",
895 + "auctionHouse": "Sotheby's",
896 + "currency": "CNY"
897 + }
898 + },
899 + "note": "Captured live by connectors/api/_auction-lib/smoke.ts on 2026-09-07 (45 records from this raw page).",
900 + "capturedAt": "2026-09-07T06:06:54.271Z"
901 +}
\ No newline at end of file
added data/fixtures/sothebys/live-1.json +958 −0
@@ -0,0 +1,958 @@
1 +{
2 + "raw": {
3 + "url": "https://www.sothebys.com/en/buy/auction/2026/important-watches-4-2",
4 + "externalId": "2ce220d0-145a-4e9c-9370-4ee277bf195c#0",
5 + "kind": "auction_lot",
6 + "engine": "api",
7 + "httpStatus": 200,
8 + "payload": {
9 + "kind": "auction_page",
10 + "auction": {
11 + "auctionId": "2ce220d0-145a-4e9c-9370-4ee277bf195c",
12 + "url": "https://www.sothebys.com/en/buy/auction/2026/important-watches-4-2",
13 + "title": "Important Watches",
14 + "saleNumber": "HK1766",
15 + "state": "Opened",
16 + "type": "Live",
17 + "departments": [
18 + "Watches"
19 + ],
20 + "currency": "HKD",
21 + "location": "Hong Kong",
22 + "startsAt": "2026-09-18T03:00Z",
23 + "endsAt": "2026-09-18T03:00Z",
24 + "closedAt": null,
25 + "totalLots": 405
26 + },
27 + "offset": 0,
28 + "lots": [
29 + {
30 + "lotId": "1fabbc51-b69b-400f-8690-a6e970116c47",
31 + "lotNumber": "2201",
32 + "title": "A limited edition set of two pens, Circa 2008",
33 + "creators": "F.P. Journe",
34 + "slug": "a-limited-edition-set-of-two-pens-circa-2008",
35 + "estimateLow": 42000,
36 + "estimateHigh": 60000,
37 + "isClosed": false,
38 + "closingTime": null,
39 + "currentBid": null,
40 + "bidCurrency": null,
41 + "isSold": false,
42 + "finalPrice": null,
43 + "finalCurrency": null,
44 + "numberOfBids": 1,
45 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/0916fa5/2147483647/strip/true/crop/1500x2000+0+0/resize/4096x5461!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fb4%2Fad%2F1321d29c431f8326254a1f55c3e2%2Fhk1766-dpxqm-090-05-t3-en01.jpg",
46 + "withdrawn": false
47 + },
48 + {
49 + "lotId": "c79474f4-923b-4b3a-b27e-2a4328367b2a",
50 + "lotNumber": "2202",
51 + "title": "No. 8 | A brand new stainless steel jumping hour wristwatch with retrograde minute indication, Circa 2026",
52 + "creators": "Ōtsuka Lōtec ",
53 + "slug": "no-8-a-brand-new-stainless-steel-jumping-hour",
54 + "estimateLow": 100000,
55 + "estimateHigh": 200000,
56 + "isClosed": false,
57 + "closingTime": null,
58 + "currentBid": null,
59 + "bidCurrency": null,
60 + "isSold": false,
61 + "finalPrice": null,
62 + "finalCurrency": null,
63 + "numberOfBids": 3,
64 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/ee7b979/2147483647/strip/true/crop/3543x3543+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F79%2F11%2Fe47fe839450f8c19d607a988c7ce%2Fhk1766-dq3ly-103-03-t3-01.jpg",
65 + "withdrawn": false
66 + },
67 + {
68 + "lotId": "0ef26304-c0e3-4cd6-9dd5-787c8ed7d48b",
69 + "lotNumber": "2203",
70 + "title": "Pendulette Réveil Souveraine | A stainless steel desk clock with alarm, Circa 2020",
71 + "creators": "F.P. Journe",
72 + "slug": "pendulette-reveil-souveraine-a-stainless-steel",
73 + "estimateLow": 50000,
74 + "estimateHigh": 200000,
75 + "isClosed": false,
76 + "closingTime": null,
77 + "currentBid": null,
78 + "bidCurrency": null,
79 + "isSold": false,
80 + "finalPrice": null,
81 + "finalCurrency": null,
82 + "numberOfBids": null,
83 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/e586ed9/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F87%2F51%2F315090bc4b7e9c312b5ae3d3f159%2Fhk1766-dnnkh-025-13-t3-01.jpg",
84 + "withdrawn": false
85 + },
86 + {
87 + "lotId": "0b23c322-38aa-4d15-9c87-5bf6cac1b716",
88 + "lotNumber": "2204",
89 + "title": "Antarctique Passage de Drake “Glacier Blue” | A stainless steel bracelet watch with date, Circa 2024",
90 + "creators": "Czapek",
91 + "slug": "antarctique-passage-de-drake-glacier-blue-a",
92 + "estimateLow": 80000,
93 + "estimateHigh": 160000,
94 + "isClosed": false,
95 + "closingTime": null,
96 + "currentBid": null,
97 + "bidCurrency": null,
98 + "isSold": false,
99 + "finalPrice": null,
100 + "finalCurrency": null,
101 + "numberOfBids": null,
102 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/f938a50/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F71%2Fa6%2F65021f7940f38e168e4dcc6456f9%2Fhk1766-dq3pd-017-19-t3-01.jpg",
103 + "withdrawn": false
104 + },
105 + {
106 + "lotId": "39184802-aeeb-4d6b-a12f-548fbcfe8da0",
107 + "lotNumber": "2205",
108 + "title": "Type 8 | A titanium wristwatch with rotating dial, Circa 2023",
109 + "creators": "Ressence",
110 + "slug": "type-8-a-titanium-wristwatch-with-rotating-dial",
111 + "estimateLow": 100000,
112 + "estimateHigh": 200000,
113 + "isClosed": false,
114 + "closingTime": null,
115 + "currentBid": null,
116 + "bidCurrency": null,
117 + "isSold": false,
118 + "finalPrice": null,
119 + "finalCurrency": null,
120 + "numberOfBids": 1,
121 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/6208594/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F65%2F68%2F3c2b22c24c109b4ea3af82952570%2Fhk1766-dq2sf-17-21-t3-01.jpg",
122 + "withdrawn": false
123 + },
124 + {
125 + "lotId": "118ffaea-7769-42fe-8714-091c94da550a",
126 + "lotNumber": "2206",
127 + "title": "Royal Oak Offshore Complete Calendar, Reference 25807ST | A stainless steel triple calendar bracelet watch, Circa 2004",
128 + "creators": "Audemars Piguet",
129 + "slug": "royal-oak-offshore-complete-calendar-reference",
130 + "estimateLow": 150000,
131 + "estimateHigh": 300000,
132 + "isClosed": false,
133 + "closingTime": null,
134 + "currentBid": null,
135 + "bidCurrency": null,
136 + "isSold": false,
137 + "finalPrice": null,
138 + "finalCurrency": null,
139 + "numberOfBids": null,
140 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/581a876/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Ff5%2F33%2F6d3a0a0b4b70912673474e95dfd2%2Fhk1766-dnlv8-023-07-t3-01.jpg",
141 + "withdrawn": false
142 + },
143 + {
144 + "lotId": "9b73a3b1-e41f-4886-8ec9-06e0d38bcc78",
145 + "lotNumber": "2207",
146 + "title": "Reference 2225 | A yellow gold and diamond-set wristwatch with polychrome enamel dial, Circa 1995",
147 + "creators": "Jaquet Droz",
148 + "slug": "reference-2225-a-yellow-gold-and-diamond-set",
149 + "estimateLow": 80000,
150 + "estimateHigh": 160000,
151 + "isClosed": false,
152 + "closingTime": null,
153 + "currentBid": null,
154 + "bidCurrency": null,
155 + "isSold": false,
156 + "finalPrice": null,
157 + "finalCurrency": null,
158 + "numberOfBids": null,
159 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/5e50790/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fe9%2F31%2F571f6f7d46779d80bd299ee1326d%2Fhk1766-dpqf3-068-11-t3-01.jpg",
160 + "withdrawn": false
161 + },
162 + {
163 + "lotId": "050b77db-6247-4652-8f50-ba2621b1c241",
164 + "lotNumber": "2208",
165 + "title": "San Marco \"Chung Chun\", Reference 139-70-9 | A limited edition platinum wristwatch with cloisonné enamel dial, Circa 1998",
166 + "creators": "Ulysse Nardin",
167 + "slug": "san-marco-chung-chun-reference-139-70-9-a-limited",
168 + "estimateLow": 80000,
169 + "estimateHigh": 160000,
170 + "isClosed": false,
171 + "closingTime": null,
172 + "currentBid": null,
173 + "bidCurrency": null,
174 + "isSold": false,
175 + "finalPrice": null,
176 + "finalCurrency": null,
177 + "numberOfBids": 2,
178 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/a0d31a8/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F21%2Fa7%2F00a658ac4f9e87ed33e81e8e9939%2Fhk1766-dpfvh-051-05-t3-01.jpg",
179 + "withdrawn": false
180 + },
181 + {
182 + "lotId": "6f5d166d-b22b-4a66-abcd-1f09804f0ef1",
183 + "lotNumber": "2210",
184 + "title": "Master Minute Repeater, Reference 164 T4 50 | A limited edition titanium semi-skeletonised minute repeating wristwatch with spring torque and power reserve indication, Circa 2006",
185 + "creators": "Jaeger-LeCoultre",
186 + "slug": "master-minute-repeater-reference-164-t4-50-a",
187 + "estimateLow": 300000,
188 + "estimateHigh": 500000,
189 + "isClosed": false,
190 + "closingTime": null,
191 + "currentBid": null,
192 + "bidCurrency": null,
193 + "isSold": false,
194 + "finalPrice": null,
195 + "finalCurrency": null,
196 + "numberOfBids": null,
197 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/adca1f0/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fe8%2Fdb%2F7120896e4281ae098116bb9bd777%2Fhk1766-dpt9c-084-06-t2-01.jpg",
198 + "withdrawn": false
199 + },
200 + {
201 + "lotId": "89c527bb-fe1c-4dd9-89d4-b1eebf9d1156",
202 + "lotNumber": "2211",
203 + "title": "Royal Oak Quantieme Perpetuel, Reference 26574ST.OO.1220ST.02 | A stainless steel perpetual calendar bracelet watch with moon phases, 52 weeks and leap year indication, Circa 2016",
204 + "creators": "Audemars Piguet",
205 + "slug": "royal-oak-quantieme-perpetuel-reference-26574st-oo",
206 + "estimateLow": 600000,
207 + "estimateHigh": 800000,
208 + "isClosed": false,
209 + "closingTime": null,
210 + "currentBid": null,
211 + "bidCurrency": null,
212 + "isSold": false,
213 + "finalPrice": null,
214 + "finalCurrency": null,
215 + "numberOfBids": null,
216 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/d19f252/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F9a%2Fad%2Fcaa09ed84e0ebda67b0db9d8168c%2Fhk1766-dpxq6-090-01-t3-01.jpg",
217 + "withdrawn": false
218 + },
219 + {
220 + "lotId": "a1aa7b8c-c64d-42c8-b621-cdefc0404b8b",
221 + "lotNumber": "2212",
222 + "title": "Carillon Tourbillon, Reference BRRP48GTBMR | A limited edition pink gold semi-skeletonised carillon minute repeating tourbillon wristwatch with power reserve indication, Circa 2013",
223 + "creators": "Bulgari | Daniel Roth",
224 + "slug": "carillon-tourbillon-reference-brrp48gtbmr-a",
225 + "estimateLow": 450000,
226 + "estimateHigh": 800000,
227 + "isClosed": false,
228 + "closingTime": null,
229 + "currentBid": null,
230 + "bidCurrency": null,
231 + "isSold": false,
232 + "finalPrice": null,
233 + "finalCurrency": null,
234 + "numberOfBids": null,
235 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/7db88d8/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F55%2F02%2F6c0cbceb4c2389ab74622516ef38%2Fhk1766-dpwf7-086-01-t2-01.jpg",
236 + "withdrawn": false
237 + },
238 + {
239 + "lotId": "dac0f236-0b89-4d03-b45f-ab59aef70bbc",
240 + "lotNumber": "2213",
241 + "title": "Royal Oak 'Jumbo' Extra-Thin, Reference 15202IP.OO.1240IP.01 | A brand new limited edition platinum and titanium bracelet watch with date, Circa 2018",
242 + "creators": "Audemars Piguet",
243 + "slug": "royal-oak-jumbo-extra-thin-reference-15202ip-oo",
244 + "estimateLow": 700000,
245 + "estimateHigh": 1500000,
246 + "isClosed": false,
247 + "closingTime": null,
248 + "currentBid": null,
249 + "bidCurrency": null,
250 + "isSold": false,
251 + "finalPrice": null,
252 + "finalCurrency": null,
253 + "numberOfBids": 1,
254 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/8a95b50/2147483647/strip/true/crop/3543x3543+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F63%2F69%2F3a6fa7a6471fa35a65dca14b0d15%2Fhk1766-d4qf9-079-01-t1-01.jpg",
255 + "withdrawn": false
256 + },
257 + {
258 + "lotId": "382cc085-a582-451a-b33a-eee7358e5134",
259 + "lotNumber": "2214",
260 + "title": "Luminor 1950 Tourbillon GMT, Reference PAM276 | A limited edition stainless steel dual time tourbillon wristwatch with power reserve indication, Circa 2008",
261 + "creators": "Panerai",
262 + "slug": "luminor-1950-tourbillon-gmt-reference-pam276-a",
263 + "estimateLow": 200000,
264 + "estimateHigh": 300000,
265 + "isClosed": false,
266 + "closingTime": null,
267 + "currentBid": null,
268 + "bidCurrency": null,
269 + "isSold": false,
270 + "finalPrice": null,
271 + "finalCurrency": null,
272 + "numberOfBids": null,
273 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/c53ba7e/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F2d%2F0f%2F9439a08349998768173e4676d1da%2Fhk1766-dpxqj-090-03-t3-01.jpg",
274 + "withdrawn": false
275 + },
276 + {
277 + "lotId": "d15a0f05-e557-40f2-8e31-3cca605cfa8c",
278 + "lotNumber": "2215",
279 + "title": "Lo Scienziato Radiomir Tourbillon GMT Ceramica, Reference PAM348 | A limited edition black ceramic skeletonised dual time tourbillon wristwatch with power reserve indication, Circa 2010",
280 + "creators": "Panerai",
281 + "slug": "lo-scienziato-radiomir-tourbillon-gmt-ceramica",
282 + "estimateLow": 240000,
283 + "estimateHigh": 400000,
284 + "isClosed": false,
285 + "closingTime": null,
286 + "currentBid": null,
287 + "bidCurrency": null,
288 + "isSold": false,
289 + "finalPrice": null,
290 + "finalCurrency": null,
291 + "numberOfBids": null,
292 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/a25f597/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F61%2Fc7%2Fc2f30c674147a24287f7bd60a9d2%2Fhk1766-dpxqk-005-12-t3-01.jpg",
293 + "withdrawn": false
294 + },
295 + {
296 + "lotId": "c69ebc7e-48a8-47a1-b595-b95da10ed243",
297 + "lotNumber": "2216",
298 + "title": "Royal Oak \"50th Anniversary\", Reference 77350CE | A black ceramic bracelet watch with date, Circa 2022",
299 + "creators": "Audemars Piguet",
300 + "slug": "royal-oak-50th-anniversary-reference-77350ce-a",
301 + "estimateLow": 350000,
302 + "estimateHigh": 500000,
303 + "isClosed": false,
304 + "closingTime": null,
305 + "currentBid": null,
306 + "bidCurrency": null,
307 + "isSold": false,
308 + "finalPrice": null,
309 + "finalCurrency": null,
310 + "numberOfBids": null,
311 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/ce74235/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Ff7%2Fa0%2Fe94091d44af7a3c016b96a28d79f%2Fhk1766-dq27z-099-05-t2-01.jpg",
312 + "withdrawn": false
313 + },
314 + {
315 + "lotId": "e62ea79e-75c6-4081-b949-cb1d5a5bf833",
316 + "lotNumber": "2217",
317 + "title": "1521 NH | A stainless steel dual time wristwatch with three-dimensional globe dial and mother-of-pearl chapter ring, Circa 2004",
318 + "creators": "Magellan",
319 + "slug": "1521-nh-a-stainless-steel-dual-time-wristwatch",
320 + "estimateLow": 42000,
321 + "estimateHigh": 80000,
322 + "isClosed": false,
323 + "closingTime": null,
324 + "currentBid": null,
325 + "bidCurrency": null,
326 + "isSold": false,
327 + "finalPrice": null,
328 + "finalCurrency": null,
329 + "numberOfBids": null,
330 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/a07abb9/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F8d%2F71%2F3cf622244b8894ee93178c62c12b%2Fhk1766-dpfv6-048-04-t3-01.jpg",
331 + "withdrawn": true
332 + },
333 + {
334 + "lotId": "cf2595f6-01b0-4a9b-b30d-bafaab4d53b0",
335 + "lotNumber": "2218",
336 + "title": "Type 8 | A titanium wristwatch with rotating dial, Circa 2023",
337 + "creators": "Ressence",
338 + "slug": "type-8-a-titanium-wristwatch-with-rotating-dial-2",
339 + "estimateLow": 80000,
340 + "estimateHigh": 120000,
341 + "isClosed": false,
342 + "closingTime": null,
343 + "currentBid": null,
344 + "bidCurrency": null,
345 + "isSold": false,
346 + "finalPrice": null,
347 + "finalCurrency": null,
348 + "numberOfBids": 1,
349 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/393ce9d/2147483647/strip/true/crop/3543x3543+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F94%2Fbd%2Fb7c7d2e24798959fa1733d099321%2Fhk1766-d3n4t-17-20-t3-01.jpg",
350 + "withdrawn": false
351 + },
352 + {
353 + "lotId": "e9f1f354-8acd-4989-b036-750ae2ffb1d7",
354 + "lotNumber": "2219",
355 + "title": "Excalibur Spider Double Tourbillon, Reference DBEX0674 | A limited edition pink gold and forged carbon skeletonised double flying tourbillon wristwatch with power reserve indication, Circa 2018",
356 + "creators": "Roger Dubuis",
357 + "slug": "excalibur-spider-double-tourbillon-reference",
358 + "estimateLow": 500000,
359 + "estimateHigh": 800000,
360 + "isClosed": false,
361 + "closingTime": null,
362 + "currentBid": null,
363 + "bidCurrency": null,
364 + "isSold": false,
365 + "finalPrice": null,
366 + "finalCurrency": null,
367 + "numberOfBids": null,
368 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/343bf8f/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F92%2F48%2F7b6b1f3348c187dcfe3f5df5581d%2Fhk1766-dpqf7-069-01-t2-01.jpg",
369 + "withdrawn": false
370 + },
371 + {
372 + "lotId": "3be39b56-1672-479a-b708-95a59567850e",
373 + "lotNumber": "2220",
374 + "title": "Streamliner Flyback Chronograph ‘Funky Blue’, Reference 6902-1201 | A stainless steel flyback chronograph bracelet watch, Circa 2023",
375 + "creators": "H. Moser & Cie",
376 + "slug": "streamliner-flyback-chronograph-funky-blue",
377 + "estimateLow": 120000,
378 + "estimateHigh": 240000,
379 + "isClosed": false,
380 + "closingTime": null,
381 + "currentBid": null,
382 + "bidCurrency": null,
383 + "isSold": false,
384 + "finalPrice": null,
385 + "finalCurrency": null,
386 + "numberOfBids": 1,
387 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/7a9d070/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fb0%2Fe0%2Ff342e7ee4becacff22c373f60f13%2Fhk1766-dpxqb-090-02-t2-01.jpg",
388 + "withdrawn": false
389 + },
390 + {
391 + "lotId": "947cc41c-e551-499a-bbda-d4872fbbd306",
392 + "lotNumber": "2222",
393 + "title": "Classic Origin ‘Revolution & The Rake’ | A limited edition stainless steel wristwatch with sector dial and bracelet, Circa 2021",
394 + "creators": "Laurent Ferrier",
395 + "slug": "classic-origin-revolution-the-rake-a-limited",
396 + "estimateLow": 200000,
397 + "estimateHigh": 400000,
398 + "isClosed": false,
399 + "closingTime": null,
400 + "currentBid": null,
401 + "bidCurrency": null,
402 + "isSold": false,
403 + "finalPrice": null,
404 + "finalCurrency": null,
405 + "numberOfBids": 1,
406 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/7d65582/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fed%2F73%2F7a4911694f7d9869be710d42ffe5%2Fhk1766-dnlv6-023-05-t3-01.jpg",
407 + "withdrawn": false
408 + },
409 + {
410 + "lotId": "0bd85034-4edc-4ded-92a4-23f421ad3fa7",
411 + "lotNumber": "2223",
412 + "title": "Pilote / Driver | An unusual limited edition, deeply curved rectangular white gold driver’s rear-wound wristwatch with integrated white gold deployant buckle, Circa 1998",
413 + "creators": "Cartier, Paris",
414 + "slug": "pilote-driver-an-unusual-limited-edition-deeply",
415 + "estimateLow": 50000,
416 + "estimateHigh": 65000,
417 + "isClosed": false,
418 + "closingTime": null,
419 + "currentBid": null,
420 + "bidCurrency": null,
421 + "isSold": false,
422 + "finalPrice": null,
423 + "finalCurrency": null,
424 + "numberOfBids": 4,
425 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/ee7359d/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F24%2F55%2Fcfebb0b3487f8e05ae6010bd54dc%2Fhk1766-dkmc9-t1-01.jpg",
426 + "withdrawn": false
427 + },
428 + {
429 + "lotId": "bbeaaaa0-33a7-4e57-9b67-9464f851ad60",
430 + "lotNumber": "2224",
431 + "title": "Pilote / Driver | An unusual limited edition deeply curved rectangular yellow gold driver’s rear-wound wristwatch with integrated gold deployant buckle, Circa 1997",
432 + "creators": "Cartier, Paris",
433 + "slug": "pilote-driver-an-unusual-limited-edition-deeply-2",
434 + "estimateLow": 40000,
435 + "estimateHigh": 65000,
436 + "isClosed": false,
437 + "closingTime": null,
438 + "currentBid": null,
439 + "bidCurrency": null,
440 + "isSold": false,
441 + "finalPrice": null,
442 + "finalCurrency": null,
443 + "numberOfBids": 4,
444 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/f2c6490/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Ff4%2Fe5%2F3853d84545e8925373c19600c42a%2Fhk1766-dkmbz-t1-01.jpg",
445 + "withdrawn": false
446 + },
447 + {
448 + "lotId": "9dc7a890-a50b-4cf2-b110-eb62247dd6fa",
449 + "lotNumber": "2225",
450 + "title": "Driver, Reference 2453B | An unusual and very rare limited edition, deeply curved rectangular white gold driver’s rear-wound wristwatch with integrated white gold deployant buckle, Circa 1999",
451 + "creators": "Cartier",
452 + "slug": "driver-reference-2453b-an-unusual-and-very-rare",
453 + "estimateLow": 55000,
454 + "estimateHigh": 80000,
455 + "isClosed": false,
456 + "closingTime": null,
457 + "currentBid": null,
458 + "bidCurrency": null,
459 + "isSold": false,
460 + "finalPrice": null,
461 + "finalCurrency": null,
462 + "numberOfBids": 6,
463 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/3639c0e/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Ff9%2F10%2Fb03c5cc34a998f5455d8bf36e7b6%2Fhk1766-dkmdq-t1-01.jpg",
464 + "withdrawn": false
465 + },
466 + {
467 + "lotId": "b19b39e2-83f3-423c-826c-073669e6ab0e",
468 + "lotNumber": "2226",
469 + "title": "Tank Basculante \"CPCP\", Reference 2499 | A yellow gold reversible wristwatch, Circa 2000",
470 + "creators": "Cartier",
471 + "slug": "tank-basculante-cpcp-reference-2499-a-yellow-gold",
472 + "estimateLow": 120000,
473 + "estimateHigh": 200000,
474 + "isClosed": false,
475 + "closingTime": null,
476 + "currentBid": null,
477 + "bidCurrency": null,
478 + "isSold": false,
479 + "finalPrice": null,
480 + "finalCurrency": null,
481 + "numberOfBids": 1,
482 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/01cd4b9/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fdd%2Ff7%2F9a13b3b8456f8bd30eed57d90af1%2Fhk1766-dphgr-054-01-t2-01.jpg",
483 + "withdrawn": false
484 + },
485 + {
486 + "lotId": "a2c466fd-b7c9-4445-8fca-24169666fe39",
487 + "lotNumber": "2227",
488 + "title": "Santos Dumont, Reference 1575 1 | A limited edition platinum wristwatch, Circa 1994",
489 + "creators": "Cartier",
490 + "slug": "santos-dumont-reference-1575-1-a-limited-edition",
491 + "estimateLow": 200000,
492 + "estimateHigh": 600000,
493 + "isClosed": false,
494 + "closingTime": null,
495 + "currentBid": null,
496 + "bidCurrency": null,
497 + "isSold": false,
498 + "finalPrice": null,
499 + "finalCurrency": null,
500 + "numberOfBids": null,
501 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/c151b0a/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F65%2F83%2Fe9a7fde9463c9f085179fcea27a4%2Fhk1766-dnnkb-025-08-t3-01.jpg",
502 + "withdrawn": false
503 + },
504 + {
505 + "lotId": "c0a08bc2-65ff-4189-ba3e-a73a09cecc37",
506 + "lotNumber": "2228",
507 + "title": "Tank à Guichets \"CPCP\", Reference 2817 | A limited edition pink gold jumping hour wristwatch, Circa 2004",
508 + "creators": "Cartier",
509 + "slug": "tank-a-guichets-cpcp-reference-2817-a-limited",
510 + "estimateLow": 400000,
511 + "estimateHigh": 700000,
512 + "isClosed": false,
513 + "closingTime": null,
514 + "currentBid": null,
515 + "bidCurrency": null,
516 + "isSold": false,
517 + "finalPrice": null,
518 + "finalCurrency": null,
519 + "numberOfBids": 3,
520 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/1061f2c/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fb0%2F6a%2Fb83d949d4d8e9414e1bcefb29398%2Fhk1766-dq6g9-114-02-t2-01.jpg",
521 + "withdrawn": false
522 + },
523 + {
524 + "lotId": "67ed422a-6267-4b22-96e4-06169c228ea8",
525 + "lotNumber": "2229",
526 + "title": "New York retailed | Clip de Revers | A yellow and pink gold, diamond and ruby-set lyre-form clip watch, Circa 1937",
527 + "creators": "Cartier",
528 + "slug": "new-york-retailed-clip-de-revers-a-yellow-and-pink",
529 + "estimateLow": 40000,
530 + "estimateHigh": 65000,
531 + "isClosed": false,
532 + "closingTime": null,
533 + "currentBid": null,
534 + "bidCurrency": null,
535 + "isSold": false,
536 + "finalPrice": null,
537 + "finalCurrency": null,
538 + "numberOfBids": 2,
539 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/7350c11/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fa6%2Fa0%2Ffcf00b37440ead606ad0ac72c180%2Fhk1766-dklzr-t1-01.jpg",
540 + "withdrawn": false
541 + },
542 + {
543 + "lotId": "f9715f53-2f19-40ad-a786-93cf395a6001",
544 + "lotNumber": "2230",
545 + "title": "A yellow gold purse watch with black dial and sliding covers, Circa 1955",
546 + "creators": "Movado for Cartier, Paris",
547 + "slug": "a-yellow-gold-purse-watch-with-black-dial-and",
548 + "estimateLow": 32000,
549 + "estimateHigh": 50000,
550 + "isClosed": false,
551 + "closingTime": null,
552 + "currentBid": null,
553 + "bidCurrency": null,
554 + "isSold": false,
555 + "finalPrice": null,
556 + "finalCurrency": null,
557 + "numberOfBids": 1,
558 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/2226054/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F2e%2F8e%2F079a5197445194addfe1acd4e2ab%2Fhk1766-dn9ph-t1-02.jpg",
559 + "withdrawn": false
560 + },
561 + {
562 + "lotId": "9168a4ea-71fe-4347-8270-a983bf9e89a6",
563 + "lotNumber": "2231",
564 + "title": "New York retailed | Clip de Revers | A yellow gold lapel clip watch with movement by James Schulz, Circa 1945",
565 + "creators": "Cartier, James Schulz",
566 + "slug": "new-york-retailed-clip-de-revers-a-yellow-gold",
567 + "estimateLow": 15000,
568 + "estimateHigh": 20000,
569 + "isClosed": false,
570 + "closingTime": null,
571 + "currentBid": null,
572 + "bidCurrency": null,
573 + "isSold": false,
574 + "finalPrice": null,
575 + "finalCurrency": null,
576 + "numberOfBids": 1,
577 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/d303ef0/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F36%2Ff4%2F9020a62f4f6d9f84fb56c4a420a5%2Fhk1766-dn9qj-t1-01.jpg",
578 + "withdrawn": false
579 + },
580 + {
581 + "lotId": "20aca3c4-57cd-4a3c-94df-7f3c5f157098",
582 + "lotNumber": "2232",
583 + "title": "A yellow gold hundred francs coin watch, Circa 1930",
584 + "creators": "Cartier",
585 + "slug": "a-yellow-gold-hundred-francs-coin-watch-circa-1930",
586 + "estimateLow": 80000,
587 + "estimateHigh": 160000,
588 + "isClosed": false,
589 + "closingTime": null,
590 + "currentBid": null,
591 + "bidCurrency": null,
592 + "isSold": false,
593 + "finalPrice": null,
594 + "finalCurrency": null,
595 + "numberOfBids": null,
596 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/a572f11/2147483647/strip/true/crop/3543x3543+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F03%2Fe3%2F7aa9151f49da908b603ebc1a0e19%2Fhk1766-dn8l5-012-01-t3-06.jpg",
597 + "withdrawn": false
598 + },
599 + {
600 + "lotId": "56b5b0e5-211c-4819-9812-296b46c3ed6c",
601 + "lotNumber": "2233",
602 + "title": "Tank Chinoise \"CPCP\", Reference 2685G | A limited edition platinum wristwatch, Circa 2005",
603 + "creators": "Cartier",
604 + "slug": "tank-chinoise-cpcp-reference-2685g-a-limited",
605 + "estimateLow": 150000,
606 + "estimateHigh": 300000,
607 + "isClosed": false,
608 + "closingTime": null,
609 + "currentBid": null,
610 + "bidCurrency": null,
611 + "isSold": false,
612 + "finalPrice": null,
613 + "finalCurrency": null,
614 + "numberOfBids": null,
615 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/7b0f857/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fe3%2Fd1%2Ff1fb0c144caab44bce4e8ce86630%2Fhk1766-dpcxv-023-11-t3-01.jpg",
616 + "withdrawn": false
617 + },
618 + {
619 + "lotId": "be0b0bb1-4189-41a7-9de6-00b2775f896c",
620 + "lotNumber": "2234",
621 + "title": "Cloche \"Collection Privé\", Reference WGCC0004 | A limited edition platinum wristwatch, Circa 2021",
622 + "creators": "Cartier",
623 + "slug": "cloche-collection-prive-reference-wgcc0004-a",
624 + "estimateLow": 280000,
625 + "estimateHigh": 400000,
626 + "isClosed": false,
627 + "closingTime": null,
628 + "currentBid": null,
629 + "bidCurrency": null,
630 + "isSold": false,
631 + "finalPrice": null,
632 + "finalCurrency": null,
633 + "numberOfBids": 1,
634 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/7c0ad5e/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fc9%2Fc4%2F2414c2fc401285816173a7606278%2Fhk1766-dnlvy-023-08-t3-01.jpg",
635 + "withdrawn": false
636 + },
637 + {
638 + "lotId": "dd83b3fb-962d-445f-8b21-a1ca375091de",
639 + "lotNumber": "2235",
640 + "title": "Tortue, Reference WGTO0008 | A limited edition platinum wristwatch, Circa 2024",
641 + "creators": "Cartier",
642 + "slug": "tortue-reference-wgto0008-a-limited-edition",
643 + "estimateLow": 120000,
644 + "estimateHigh": 200000,
645 + "isClosed": false,
646 + "closingTime": null,
647 + "currentBid": null,
648 + "bidCurrency": null,
649 + "isSold": false,
650 + "finalPrice": null,
651 + "finalCurrency": null,
652 + "numberOfBids": 2,
653 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/4ebdff6/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F67%2F1c%2F0871846a4a36bc1a17ff859d8dcb%2Fhk1766-dpt5v-075-01-t3-01.jpg",
654 + "withdrawn": false
655 + },
656 + {
657 + "lotId": "874dc673-ecdd-4137-bed3-bcd469459a56",
658 + "lotNumber": "2236",
659 + "title": " Tank À Vis \"CPCP\", Reference 2554 | A white gold wristwatch with date and wandering hours, Circa 2006",
660 + "creators": "Cartier",
661 + "slug": "tank-a-vis-cpcp-reference-2554-a-white-gold",
662 + "estimateLow": 240000,
663 + "estimateHigh": 480000,
664 + "isClosed": false,
665 + "closingTime": null,
666 + "currentBid": null,
667 + "bidCurrency": null,
668 + "isSold": false,
669 + "finalPrice": null,
670 + "finalCurrency": null,
671 + "numberOfBids": null,
672 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/0724b54/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fd0%2Fdb%2Fa3e25e3d48eba2410b24c9aba677%2Fhk1766-dp4bf-039-02-t2-01.jpg",
673 + "withdrawn": false
674 + },
675 + {
676 + "lotId": "7cd0a7a2-6eee-41ff-988c-d7ab238143a9",
677 + "lotNumber": "2237",
678 + "title": "An onyx, silver-gilt, gold, enamel and diamond-set 8-day desk clock, Circa 1919",
679 + "creators": "Cartier, Paris",
680 + "slug": "an-onyx-silver-gilt-gold-enamel-and-diamond-set-8",
681 + "estimateLow": 55000,
682 + "estimateHigh": 80000,
683 + "isClosed": false,
684 + "closingTime": null,
685 + "currentBid": null,
686 + "bidCurrency": null,
687 + "isSold": false,
688 + "finalPrice": null,
689 + "finalCurrency": null,
690 + "numberOfBids": 1,
691 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/0840333/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fc8%2Fa3%2F1612777140e585bedac47081610d%2Fhk1766-dnb5z-t1-01.jpg",
692 + "withdrawn": false
693 + },
694 + {
695 + "lotId": "660fc569-d778-4568-a822-97afe9108d82",
696 + "lotNumber": "2238",
697 + "title": "An agate, yellow gold, rock crystal and enamel 8-day desk clock with luminescent indexes, Circa 1926",
698 + "creators": "Cartier, Paris",
699 + "slug": "an-agate-yellow-gold-rock-crystal-and-enamel-8-day",
700 + "estimateLow": 65000,
701 + "estimateHigh": 95000,
702 + "isClosed": false,
703 + "closingTime": null,
704 + "currentBid": null,
705 + "bidCurrency": null,
706 + "isSold": false,
707 + "finalPrice": null,
708 + "finalCurrency": null,
709 + "numberOfBids": null,
710 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/13d5303/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F16%2F08%2F4a7e07e147a28a4640a37692f333%2Fhk1766-dn999-t1-01.jpg",
711 + "withdrawn": false
712 + },
713 + {
714 + "lotId": "8d7ef951-0834-4f06-8a94-0fcc5581926d",
715 + "lotNumber": "2239",
716 + "title": "Carré à Coin Coupés | A square yellow gold wristwatch with chamfered corners and cylindrical T-bar lugs, Circa 1947",
717 + "creators": "Cartier, Paris",
718 + "slug": "carre-a-coin-coupes-a-square-yellow-gold",
719 + "estimateLow": 120000,
720 + "estimateHigh": 160000,
721 + "isClosed": false,
722 + "closingTime": null,
723 + "currentBid": null,
724 + "bidCurrency": null,
725 + "isSold": false,
726 + "finalPrice": null,
727 + "finalCurrency": null,
728 + "numberOfBids": null,
729 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/702a832/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F7c%2F19%2F0a58982b4cc798990718ad092368%2Fhk1766-dkm9s-091-22-rx-t3-01.jpg",
730 + "withdrawn": false
731 + },
732 + {
733 + "lotId": "2ec2a1c6-6619-49c9-8ad7-285690ab83cd",
734 + "lotNumber": "2240",
735 + "title": "Baignoire | An oval yellow gold lady’s wristwatch with original gold deployant buckle, Circa 1966-67",
736 + "creators": "Cartier, London",
737 + "slug": "baignoire-an-oval-yellow-gold-ladys-wristwatch",
738 + "estimateLow": 120000,
739 + "estimateHigh": 160000,
740 + "isClosed": false,
741 + "closingTime": null,
742 + "currentBid": null,
743 + "bidCurrency": null,
744 + "isSold": false,
745 + "finalPrice": null,
746 + "finalCurrency": null,
747 + "numberOfBids": null,
748 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/5b5c786/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fc8%2F2d%2F036d2a204b35b49ea7007dac352f%2Fhk1766-dkm95-091-29-rx-t3-01.jpg",
749 + "withdrawn": false
750 + },
751 + {
752 + "lotId": "c4be4aa5-729a-4c55-aa2d-c09da374081f",
753 + "lotNumber": "2241",
754 + "title": "Maxi Pebble | A very rare yellow gold wristwatch with geometric off-set dial and original gold deployant buckle, Circa 1972-73",
755 + "creators": "Cartier, London",
756 + "slug": "maxi-pebble-a-very-rare-yellow-gold-wristwatch",
757 + "estimateLow": 1600000,
758 + "estimateHigh": 2200000,
759 + "isClosed": false,
760 + "closingTime": null,
761 + "currentBid": null,
762 + "bidCurrency": null,
763 + "isSold": false,
764 + "finalPrice": null,
765 + "finalCurrency": null,
766 + "numberOfBids": 1,
767 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/63e2c9b/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F0e%2Fa4%2F0bfd3b9a4c7594862d47d7f815cd%2Fhk1766-dlj4l-091-11-t1-01.jpg",
768 + "withdrawn": false
769 + },
770 + {
771 + "lotId": "24c5ffb7-cec8-4757-bccc-e6688882da4a",
772 + "lotNumber": "2242",
773 + "title": "Midi Pebble | An extremely rare mid-sized yellow gold wristwatch with geometric off-set dial and original gold deployant buckle, Circa 1973-74",
774 + "creators": "Cartier, London",
775 + "slug": "midi-pebble-an-extremely-rare-mid-sized-yellow",
776 + "estimateLow": 950000,
777 + "estimateHigh": 1500000,
778 + "isClosed": false,
779 + "closingTime": null,
780 + "currentBid": null,
781 + "bidCurrency": null,
782 + "isSold": false,
783 + "finalPrice": null,
784 + "finalCurrency": null,
785 + "numberOfBids": null,
786 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/2736b7f/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F7f%2F6d%2F4e09d0914f4196bac9eb54bb6cff%2Fhk1766-dkn63-091-46-t3-01.jpg",
787 + "withdrawn": false
788 + },
789 + {
790 + "lotId": "eaccf673-ad67-4fee-8733-e5abd0ca43a7",
791 + "lotNumber": "2243",
792 + "title": "Bamboo Coussin, Reference 78102 | A yellow gold wristwatch, Circa 1975",
793 + "creators": "Cartier",
794 + "slug": "bamboo-coussin-reference-78102-a-yellow-gold",
795 + "estimateLow": 400000,
796 + "estimateHigh": 800000,
797 + "isClosed": false,
798 + "closingTime": null,
799 + "currentBid": null,
800 + "bidCurrency": null,
801 + "isSold": false,
802 + "finalPrice": null,
803 + "finalCurrency": null,
804 + "numberOfBids": 1,
805 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/f02250d/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F77%2F1e%2Fc10676e742a5a3c13b35d18d5aa7%2Fhk1766-dmr6z-014-01-t2-01.jpg",
806 + "withdrawn": false
807 + },
808 + {
809 + "lotId": "032df186-0a6b-4531-abfd-a4805f26f329",
810 + "lotNumber": "2244",
811 + "title": "Bamboo Coussin, Reference 78110 | A yellow gold wristwatch, Circa 1975",
812 + "creators": "Cartier",
813 + "slug": "bamboo-coussin-reference-78110-a-yellow-gold",
814 + "estimateLow": 300000,
815 + "estimateHigh": 600000,
816 + "isClosed": false,
817 + "closingTime": null,
818 + "currentBid": null,
819 + "bidCurrency": null,
820 + "isSold": false,
821 + "finalPrice": null,
822 + "finalCurrency": null,
823 + "numberOfBids": 1,
824 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/67d79c8/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fe5%2F1a%2F6b0f43c04702bbcb9e5fee3fea68%2Fhk1766-dpxxk-092-01-t3-01.jpg",
825 + "withdrawn": false
826 + },
827 + {
828 + "lotId": "191e53f0-c7dc-4fab-9946-225946304fa6",
829 + "lotNumber": "2245",
830 + "title": "Reverso | A yellow gold reversible dual time wristwatch, Circa 1970",
831 + "creators": "Cartier",
832 + "slug": "reverso-a-yellow-gold-reversible-dual-time",
833 + "estimateLow": 220000,
834 + "estimateHigh": 350000,
835 + "isClosed": false,
836 + "closingTime": null,
837 + "currentBid": null,
838 + "bidCurrency": null,
839 + "isSold": false,
840 + "finalPrice": null,
841 + "finalCurrency": null,
842 + "numberOfBids": null,
843 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/c1e2fef/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fe4%2Fe1%2Fe739d08b456b8203059e70371ba4%2Fhk1766-dpwqv-089-01-t3-01.jpg",
844 + "withdrawn": false
845 + },
846 + {
847 + "lotId": "0eb0353d-ae67-48c9-8e0d-98747ffe48ef",
848 + "lotNumber": "2246",
849 + "title": "Octagonal | A very rare Lady's three colour gold octagonal bracelet watch with pink gold deployant buckle, Circa 1971",
850 + "creators": "Cartier, London",
851 + "slug": "octagonal-a-very-rare-ladys-three-colour-gold",
852 + "estimateLow": 800000,
853 + "estimateHigh": 1200000,
854 + "isClosed": false,
855 + "closingTime": null,
856 + "currentBid": null,
857 + "bidCurrency": null,
858 + "isSold": false,
859 + "finalPrice": null,
860 + "finalCurrency": null,
861 + "numberOfBids": null,
862 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/58b0ae0/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F8a%2F16%2F48c2bf4a4f14be45281f835b151a%2Fhk1766-dmr6v-013-01-t1-01.jpg",
863 + "withdrawn": false
864 + },
865 + {
866 + "lotId": "43347e62-cd7e-4481-b905-c835e88e0029",
867 + "lotNumber": "2247",
868 + "title": "Reference 3727 | A yellow gold, diamond and red agate-set bracelet watch with red agate dial, Made in 1977",
869 + "creators": "Patek Philippe",
870 + "slug": "reference-3727-a-yellow-gold-diamond-and-red-agate",
871 + "estimateLow": 200000,
872 + "estimateHigh": 400000,
873 + "isClosed": false,
874 + "closingTime": null,
875 + "currentBid": null,
876 + "bidCurrency": null,
877 + "isSold": false,
878 + "finalPrice": null,
879 + "finalCurrency": null,
880 + "numberOfBids": 2,
881 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/8143ac6/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2Fd0%2Fdb%2F07407a734bc0a476b5465e0160e7%2Fhk1766-dn4cf-005-02-t3-01.jpg",
882 + "withdrawn": false
883 + },
884 + {
885 + "lotId": "1ac2b17f-0969-46c5-b8c6-b6c8e4daa6cc",
886 + "lotNumber": "2248",
887 + "title": "London retailed | Mignonette | A silver-gilt and enamel 8-day miniature travelling clock with original Cartier London presentation case, Circa 1911",
888 + "creators": "Cartier, Paris",
889 + "slug": "london-retailed-mignonette-a-silver-gilt-and",
890 + "estimateLow": 28000,
891 + "estimateHigh": 45000,
892 + "isClosed": false,
893 + "closingTime": null,
894 + "currentBid": null,
895 + "bidCurrency": null,
896 + "isSold": false,
897 + "finalPrice": null,
898 + "finalCurrency": null,
899 + "numberOfBids": 1,
900 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/fe08f9d/2147483647/strip/true/crop/3543x3543+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2F68%2F03%2F1de869a54d5fb08759799d729e9d%2Fhk1766-dklt4-t1-01.jpg",
901 + "withdrawn": false
902 + },
903 + {
904 + "lotId": "cb4425ea-d713-4b18-a4fc-39df4f16e88e",
905 + "lotNumber": "2249",
906 + "title": "Reference 5401BA | A yellow gold skeletonised bracelet watch, Circa 1971",
907 + "creators": "Audemars Piguet",
908 + "slug": "reference-5401ba-a-yellow-gold-skeletonised",
909 + "estimateLow": 200000,
910 + "estimateHigh": 400000,
911 + "isClosed": false,
912 + "closingTime": null,
913 + "currentBid": null,
914 + "bidCurrency": null,
915 + "isSold": false,
916 + "finalPrice": null,
917 + "finalCurrency": null,
918 + "numberOfBids": 1,
919 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/2fbbed1/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F98%2F0b%2F2e504c9949059654bf85dbfbfd9f%2Fhk1766-dnkx2-021-01-t3-01.jpg",
920 + "withdrawn": false
921 + },
922 + {
923 + "lotId": "91844ee6-3b68-4d3e-87d1-f384857a639b",
924 + "lotNumber": "2250",
925 + "title": "Audemars Piguet | A white gold and diamond-set skeletonised bracelet watch, Circa 1990",
926 + "creators": "Audemars Piguet",
927 + "slug": "audemars-piguet-a-white-gold-and-diamond-set",
928 + "estimateLow": 240000,
929 + "estimateHigh": 400000,
930 + "isClosed": false,
931 + "closingTime": null,
932 + "currentBid": null,
933 + "bidCurrency": null,
934 + "isSold": false,
935 + "finalPrice": null,
936 + "finalCurrency": null,
937 + "numberOfBids": null,
938 + "imageUrl": "https://sothebys-md.brightspotcdn.com/dims4/default/5dc1adb/2147483647/strip/true/crop/2000x2000+0+0/resize/4096x4096!/quality/90/?url=http%3A%2F%2Fsothebys-brightspot.s3.amazonaws.com%2Fmedia-desk%2Fwebnative%2Fimages%2F01%2F5a%2Ff3533e5844868dc47da83143ed0f%2Fhk1766-dpt63-80-01-t3-01.jpg",
939 + "withdrawn": false
940 + }
941 + ]
942 + },
943 + "fetchedAt": "2026-09-07T06:06:54.864Z"
944 + },
945 + "expect": {
946 + "minCount": 1,
947 + "kinds": [
948 + "auction_lot"
949 + ],
950 + "first": {
951 + "kind": "auction_lot",
952 + "auctionHouse": "Sotheby's",
953 + "currency": "HKD"
954 + }
955 + },
956 + "note": "Captured live by connectors/api/_auction-lib/smoke.ts on 2026-09-07 (47 records from this raw page).",
957 + "capturedAt": "2026-09-07T06:06:54.871Z"
958 +}
\ No newline at end of file
959