@jukasdrj/bookstrack-api-client 1.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/schema.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * Do not make direct changes to the file.
4
4
  */
5
5
  export interface paths {
6
- "/health": {
6
+ "/v3/capabilities": {
7
7
  parameters: {
8
8
  query?: never;
9
9
  header?: never;
@@ -11,80 +11,30 @@ export interface paths {
11
11
  cookie?: never;
12
12
  };
13
13
  /**
14
- * Health check endpoint
15
- * @description Simple health check that returns worker status.
16
- *
17
- * Returns basic worker information for monitoring purposes:
18
- * - **status**: Health status indicator (always "ok" when responding)
19
- * - **worker**: Worker service name
20
- * - **version**: API version
21
- * - **router**: Router framework type
22
- *
23
- * **Example:** `GET /health`
24
- *
25
- * This endpoint is publicly accessible and requires no authentication.
26
- * Use it for:
27
- * - Monitoring and uptime checks
28
- * - Load balancer health gates
29
- * - CI/CD pipeline verification
14
+ * Get API capabilities
15
+ * @description Returns API feature availability, limits, and deprecation notices. Clients should call this on app startup.
30
16
  */
31
- get: {
32
- parameters: {
33
- query?: never;
34
- header?: never;
35
- path?: never;
36
- cookie?: never;
37
- };
38
- requestBody?: never;
39
- responses: {
40
- /** @description Health check successful */
41
- 200: {
42
- headers: {
43
- [name: string]: unknown;
44
- };
45
- content: {
46
- /**
47
- * @example {
48
- * "data": {
49
- * "status": "ok",
50
- * "worker": "api-worker",
51
- * "version": "2.1.0",
52
- * "router": "hono"
53
- * },
54
- * "metadata": {
55
- * "timestamp": "2025-11-28T12:00:00.000Z"
56
- * }
57
- * }
58
- */
59
- "application/json": {
60
- data: {
61
- /**
62
- * @description Health status indicator
63
- * @enum {string}
64
- */
65
- status: "ok";
66
- /** @description Worker service name */
67
- worker: string;
68
- /** @description API version */
69
- version: string;
70
- /**
71
- * @description Router framework
72
- * @enum {string}
73
- */
74
- router: "hono";
75
- };
76
- metadata?: {
77
- /**
78
- * Format: date-time
79
- * @description ISO 8601 timestamp
80
- */
81
- timestamp: string;
82
- };
83
- };
84
- };
85
- };
86
- };
17
+ get: operations["getCapabilities"];
18
+ put?: never;
19
+ post?: never;
20
+ delete?: never;
21
+ options?: never;
22
+ head?: never;
23
+ patch?: never;
24
+ trace?: never;
25
+ };
26
+ "/v3/recommendations/weekly": {
27
+ parameters: {
28
+ query?: never;
29
+ header?: never;
30
+ path?: never;
31
+ cookie?: never;
87
32
  };
33
+ /**
34
+ * Get weekly book recommendations
35
+ * @description Returns global weekly book recommendations. Non-personalized curated picks generated every Sunday at midnight UTC.
36
+ */
37
+ get: operations["getWeeklyRecommendations"];
88
38
  put?: never;
89
39
  post?: never;
90
40
  delete?: never;
@@ -93,7 +43,7 @@ export interface paths {
93
43
  patch?: never;
94
44
  trace?: never;
95
45
  };
96
- "/v1/search/isbn": {
46
+ "/v3/books/search": {
97
47
  parameters: {
98
48
  query?: never;
99
49
  header?: never;
@@ -101,506 +51,27 @@ export interface paths {
101
51
  cookie?: never;
102
52
  };
103
53
  /**
104
- * Search for a book by ISBN
105
- * @description Search for a book by ISBN-10 or ISBN-13 (digits only, no hyphens).
106
- *
107
- * Returns comprehensive book data including:
108
- * - Works: Abstract creative works (title, description, subjects)
109
- * - Editions: Physical/digital editions (publisher, publication date, format)
110
- * - Authors: Author biographical data (name, gender, cultural region)
111
- *
112
- * **Example:** `GET /v1/search/isbn?isbn=9780439708180`
113
- *
114
- * **Multi-Provider Orchestration:**
115
- * 1. BookRepository (KV/D1 cache) - fastest
116
- * 2. Google Books API - primary source
117
- * 3. OpenLibrary API - fallback #1
118
- * 4. ISBNdb API - fallback #2
119
- *
120
- * **Cache TTL:** 24 hours (KV), permanent (D1)
121
- *
122
- * **Rate Limits:**
123
- * - 100 requests/minute per IP
124
- * - 1000 requests/hour per IP
125
- *
126
- * **Circuit Breaker Protection:**
127
- * All external providers are protected by circuit breakers.
128
- * If a provider's circuit is OPEN, the request fails fast with `CIRCUIT_OPEN` error.
54
+ * Search books
55
+ * @description Unified search supporting multiple modes: text, semantic, similar
129
56
  */
130
- get: {
131
- parameters: {
132
- query: {
133
- /** @description ISBN-10 or ISBN-13 (digits only, no hyphens) */
134
- isbn: string;
135
- };
136
- header?: never;
137
- path?: never;
138
- cookie?: never;
139
- };
140
- requestBody?: never;
141
- responses: {
142
- /** @description Book found successfully */
143
- 200: {
144
- headers: {
145
- [name: string]: unknown;
146
- };
147
- content: {
148
- /**
149
- * @example {
150
- * "data": {
151
- * "works": [
152
- * {
153
- * "title": "Harry Potter and the Philosopher's Stone",
154
- * "subjectTags": [
155
- * "magic",
156
- * "wizards",
157
- * "fantasy"
158
- * ],
159
- * "firstPublicationYear": 1997,
160
- * "description": "Harry Potter has never even heard of Hogwarts...",
161
- * "coverImageURL": "https://covers.openlibrary.org/b/id/12345-L.jpg",
162
- * "primaryProvider": "google_books",
163
- * "goodreadsWorkIDs": [
164
- * "OL82563W"
165
- * ],
166
- * "amazonASINs": [
167
- * "B0192CTMYG"
168
- * ],
169
- * "librarythingIDs": [],
170
- * "googleBooksVolumeIDs": [
171
- * "wrOQLV6xB-wC"
172
- * ],
173
- * "isbndbQuality": 95,
174
- * "reviewStatus": "verified",
175
- * "synthetic": false
176
- * }
177
- * ],
178
- * "editions": [
179
- * {
180
- * "isbns": [
181
- * "9780439708180",
182
- * "0439708184"
183
- * ],
184
- * "title": "Harry Potter and the Philosopher's Stone",
185
- * "publisher": "Scholastic Inc.",
186
- * "publicationDate": "1999-09-01",
187
- * "pageCount": 309,
188
- * "format": "paperback",
189
- * "coverImageURL": "https://covers.openlibrary.org/b/isbn/9780439708180-L.jpg",
190
- * "primaryProvider": "google_books",
191
- * "amazonASINs": [
192
- * "0439708184"
193
- * ],
194
- * "googleBooksVolumeIDs": [
195
- * "wrOQLV6xB-wC"
196
- * ],
197
- * "librarythingIDs": [],
198
- * "isbndbQuality": 95
199
- * }
200
- * ],
201
- * "authors": [
202
- * {
203
- * "name": "J.K. Rowling",
204
- * "gender": "female",
205
- * "culturalRegion": "europe",
206
- * "nationality": "British",
207
- * "birthYear": 1965,
208
- * "openLibraryID": "OL23919A",
209
- * "bookCount": 42
210
- * }
211
- * ],
212
- * "resultCount": 1
213
- * },
214
- * "metadata": {
215
- * "timestamp": "2025-11-28T12:00:00.000Z",
216
- * "processingTime": 145,
217
- * "provider": "google_books",
218
- * "cached": true
219
- * }
220
- * }
221
- */
222
- "application/json": {
223
- data: {
224
- works: {
225
- title: string;
226
- subjectTags: string[];
227
- originalLanguage?: string;
228
- firstPublicationYear?: number;
229
- description?: string;
230
- /** Format: uri */
231
- coverImageURL?: string;
232
- synthetic?: boolean;
233
- /** @enum {string} */
234
- primaryProvider?: "google_books" | "open_library" | "isbndb" | "kv_cache";
235
- contributors?: ("google_books" | "open_library" | "isbndb" | "kv_cache")[];
236
- openLibraryID?: string;
237
- openLibraryWorkID?: string;
238
- isbndbID?: string;
239
- googleBooksVolumeID?: string;
240
- goodreadsID?: string;
241
- goodreadsWorkIDs: string[];
242
- amazonASINs: string[];
243
- librarythingIDs: string[];
244
- googleBooksVolumeIDs: string[];
245
- /** Format: date-time */
246
- lastISBNDBSync?: string;
247
- isbndbQuality: number;
248
- /** @enum {string} */
249
- reviewStatus: "unverified" | "verified" | "rejected" | "flagged";
250
- originalImagePath?: string;
251
- boundingBox?: {
252
- x: number;
253
- y: number;
254
- width: number;
255
- height: number;
256
- };
257
- }[];
258
- editions: {
259
- isbn?: string;
260
- isbns: string[];
261
- title?: string;
262
- publisher?: string;
263
- publicationDate?: string;
264
- pageCount?: number;
265
- /** @enum {string} */
266
- format: "hardcover" | "paperback" | "ebook" | "audiobook" | "mass_market" | "board_book" | "unknown";
267
- /** Format: uri */
268
- coverImageURL?: string;
269
- editionTitle?: string;
270
- editionDescription?: string;
271
- language?: string;
272
- /** @enum {string} */
273
- primaryProvider?: "google_books" | "open_library" | "isbndb" | "kv_cache";
274
- contributors?: ("google_books" | "open_library" | "isbndb" | "kv_cache")[];
275
- openLibraryID?: string;
276
- openLibraryEditionID?: string;
277
- isbndbID?: string;
278
- googleBooksVolumeID?: string;
279
- goodreadsID?: string;
280
- amazonASINs: string[];
281
- googleBooksVolumeIDs: string[];
282
- librarythingIDs: string[];
283
- /** Format: date-time */
284
- lastISBNDBSync?: string;
285
- isbndbQuality: number;
286
- }[];
287
- authors: {
288
- name: string;
289
- /** @enum {string} */
290
- gender: "male" | "female" | "non_binary" | "unknown";
291
- /** @enum {string} */
292
- culturalRegion?: "north_america" | "latin_america" | "europe" | "asia" | "africa" | "middle_east" | "oceania" | "unknown";
293
- nationality?: string;
294
- birthYear?: number;
295
- deathYear?: number;
296
- openLibraryID?: string;
297
- isbndbID?: string;
298
- googleBooksID?: string;
299
- goodreadsID?: string;
300
- bookCount?: number;
301
- }[];
302
- resultCount: number;
303
- };
304
- metadata?: {
305
- /** Format: date-time */
306
- timestamp: string;
307
- processingTime?: number;
308
- /** @enum {string} */
309
- provider?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "none";
310
- cached?: boolean;
311
- };
312
- };
313
- };
314
- };
315
- /** @description Invalid ISBN format */
316
- 400: {
317
- headers: {
318
- [name: string]: unknown;
319
- };
320
- content: {
321
- /**
322
- * @example {
323
- * "data": null,
324
- * "metadata": {
325
- * "timestamp": "2025-11-28T12:00:00.000Z"
326
- * },
327
- * "error": {
328
- * "code": "INVALID_ISBN",
329
- * "message": "Invalid ISBN format. Must be valid ISBN-10 or ISBN-13",
330
- * "details": {
331
- * "isbn": "invalid-isbn"
332
- * }
333
- * }
334
- * }
335
- */
336
- "application/json": {
337
- data: unknown;
338
- metadata?: {
339
- /** Format: date-time */
340
- timestamp: string;
341
- cached?: boolean;
342
- /** @enum {string} */
343
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
344
- };
345
- error: {
346
- /** @enum {string} */
347
- code: "NOT_FOUND" | "INVALID_REQUEST" | "INVALID_ISBN" | "INVALID_QUERY" | "MISSING_PARAMETER" | "UNAUTHORIZED" | "FORBIDDEN" | "INTERNAL_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "RATE_LIMIT_EXCEEDED" | "CIRCUIT_OPEN" | "PROVIDER_ERROR" | "TIMEOUT";
348
- message: string;
349
- details?: {
350
- [key: string]: unknown;
351
- };
352
- retryable?: boolean;
353
- retryAfterMs?: number;
354
- provider?: string;
355
- };
356
- };
357
- };
358
- };
359
- /** @description Book not found */
360
- 404: {
361
- headers: {
362
- [name: string]: unknown;
363
- };
364
- content: {
365
- /**
366
- * @example {
367
- * "data": {
368
- * "works": [],
369
- * "editions": [],
370
- * "authors": [],
371
- * "resultCount": 0
372
- * },
373
- * "metadata": {
374
- * "timestamp": "2025-11-28T12:00:00.000Z",
375
- * "processingTime": 523,
376
- * "provider": "none",
377
- * "cached": false
378
- * }
379
- * }
380
- */
381
- "application/json": {
382
- data: {
383
- works: {
384
- title: string;
385
- subjectTags: string[];
386
- originalLanguage?: string;
387
- firstPublicationYear?: number;
388
- description?: string;
389
- /** Format: uri */
390
- coverImageURL?: string;
391
- synthetic?: boolean;
392
- /** @enum {string} */
393
- primaryProvider?: "google_books" | "open_library" | "isbndb" | "kv_cache";
394
- contributors?: ("google_books" | "open_library" | "isbndb" | "kv_cache")[];
395
- openLibraryID?: string;
396
- openLibraryWorkID?: string;
397
- isbndbID?: string;
398
- googleBooksVolumeID?: string;
399
- goodreadsID?: string;
400
- goodreadsWorkIDs: string[];
401
- amazonASINs: string[];
402
- librarythingIDs: string[];
403
- googleBooksVolumeIDs: string[];
404
- /** Format: date-time */
405
- lastISBNDBSync?: string;
406
- isbndbQuality: number;
407
- /** @enum {string} */
408
- reviewStatus: "unverified" | "verified" | "rejected" | "flagged";
409
- originalImagePath?: string;
410
- boundingBox?: {
411
- x: number;
412
- y: number;
413
- width: number;
414
- height: number;
415
- };
416
- }[];
417
- editions: {
418
- isbn?: string;
419
- isbns: string[];
420
- title?: string;
421
- publisher?: string;
422
- publicationDate?: string;
423
- pageCount?: number;
424
- /** @enum {string} */
425
- format: "hardcover" | "paperback" | "ebook" | "audiobook" | "mass_market" | "board_book" | "unknown";
426
- /** Format: uri */
427
- coverImageURL?: string;
428
- editionTitle?: string;
429
- editionDescription?: string;
430
- language?: string;
431
- /** @enum {string} */
432
- primaryProvider?: "google_books" | "open_library" | "isbndb" | "kv_cache";
433
- contributors?: ("google_books" | "open_library" | "isbndb" | "kv_cache")[];
434
- openLibraryID?: string;
435
- openLibraryEditionID?: string;
436
- isbndbID?: string;
437
- googleBooksVolumeID?: string;
438
- goodreadsID?: string;
439
- amazonASINs: string[];
440
- googleBooksVolumeIDs: string[];
441
- librarythingIDs: string[];
442
- /** Format: date-time */
443
- lastISBNDBSync?: string;
444
- isbndbQuality: number;
445
- }[];
446
- authors: {
447
- name: string;
448
- /** @enum {string} */
449
- gender: "male" | "female" | "non_binary" | "unknown";
450
- /** @enum {string} */
451
- culturalRegion?: "north_america" | "latin_america" | "europe" | "asia" | "africa" | "middle_east" | "oceania" | "unknown";
452
- nationality?: string;
453
- birthYear?: number;
454
- deathYear?: number;
455
- openLibraryID?: string;
456
- isbndbID?: string;
457
- googleBooksID?: string;
458
- goodreadsID?: string;
459
- bookCount?: number;
460
- }[];
461
- resultCount: number;
462
- };
463
- metadata?: {
464
- /** Format: date-time */
465
- timestamp: string;
466
- processingTime?: number;
467
- /** @enum {string} */
468
- provider?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "none";
469
- cached?: boolean;
470
- };
471
- };
472
- };
473
- };
474
- /** @description Rate limit exceeded */
475
- 429: {
476
- headers: {
477
- [name: string]: unknown;
478
- };
479
- content: {
480
- /**
481
- * @example {
482
- * "data": null,
483
- * "metadata": {
484
- * "timestamp": "2025-11-28T12:00:00.000Z"
485
- * },
486
- * "error": {
487
- * "code": "RATE_LIMIT_EXCEEDED",
488
- * "message": "Rate limit exceeded. Maximum 100 requests per minute.",
489
- * "retryable": true,
490
- * "retryAfterMs": 60000
491
- * }
492
- * }
493
- */
494
- "application/json": {
495
- data: unknown;
496
- metadata?: {
497
- /** Format: date-time */
498
- timestamp: string;
499
- cached?: boolean;
500
- /** @enum {string} */
501
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
502
- };
503
- error: {
504
- /** @enum {string} */
505
- code: "NOT_FOUND" | "INVALID_REQUEST" | "INVALID_ISBN" | "INVALID_QUERY" | "MISSING_PARAMETER" | "UNAUTHORIZED" | "FORBIDDEN" | "INTERNAL_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "RATE_LIMIT_EXCEEDED" | "CIRCUIT_OPEN" | "PROVIDER_ERROR" | "TIMEOUT";
506
- message: string;
507
- details?: {
508
- [key: string]: unknown;
509
- };
510
- retryable?: boolean;
511
- retryAfterMs?: number;
512
- provider?: string;
513
- };
514
- };
515
- };
516
- };
517
- /** @description Internal server error */
518
- 500: {
519
- headers: {
520
- [name: string]: unknown;
521
- };
522
- content: {
523
- /**
524
- * @example {
525
- * "data": null,
526
- * "metadata": {
527
- * "timestamp": "2025-11-28T12:00:00.000Z"
528
- * },
529
- * "error": {
530
- * "code": "INTERNAL_ERROR",
531
- * "message": "An unexpected error occurred while processing the request"
532
- * }
533
- * }
534
- */
535
- "application/json": {
536
- data: unknown;
537
- metadata?: {
538
- /** Format: date-time */
539
- timestamp: string;
540
- cached?: boolean;
541
- /** @enum {string} */
542
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
543
- };
544
- error: {
545
- /** @enum {string} */
546
- code: "NOT_FOUND" | "INVALID_REQUEST" | "INVALID_ISBN" | "INVALID_QUERY" | "MISSING_PARAMETER" | "UNAUTHORIZED" | "FORBIDDEN" | "INTERNAL_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "RATE_LIMIT_EXCEEDED" | "CIRCUIT_OPEN" | "PROVIDER_ERROR" | "TIMEOUT";
547
- message: string;
548
- details?: {
549
- [key: string]: unknown;
550
- };
551
- retryable?: boolean;
552
- retryAfterMs?: number;
553
- provider?: string;
554
- };
555
- };
556
- };
557
- };
558
- /** @description Circuit breaker open - provider unavailable */
559
- 503: {
560
- headers: {
561
- [name: string]: unknown;
562
- };
563
- content: {
564
- /**
565
- * @example {
566
- * "data": null,
567
- * "metadata": {
568
- * "timestamp": "2025-11-28T12:00:00.000Z"
569
- * },
570
- * "error": {
571
- * "code": "CIRCUIT_OPEN",
572
- * "message": "Provider google-books circuit breaker is open. Service temporarily unavailable.",
573
- * "provider": "google-books",
574
- * "retryable": true,
575
- * "retryAfterMs": 45000
576
- * }
577
- * }
578
- */
579
- "application/json": {
580
- data: unknown;
581
- metadata?: {
582
- /** Format: date-time */
583
- timestamp: string;
584
- cached?: boolean;
585
- /** @enum {string} */
586
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
587
- };
588
- error: {
589
- /** @enum {string} */
590
- code: "NOT_FOUND" | "INVALID_REQUEST" | "INVALID_ISBN" | "INVALID_QUERY" | "MISSING_PARAMETER" | "UNAUTHORIZED" | "FORBIDDEN" | "INTERNAL_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "RATE_LIMIT_EXCEEDED" | "CIRCUIT_OPEN" | "PROVIDER_ERROR" | "TIMEOUT";
591
- message: string;
592
- details?: {
593
- [key: string]: unknown;
594
- };
595
- retryable?: boolean;
596
- retryAfterMs?: number;
597
- provider?: string;
598
- };
599
- };
600
- };
601
- };
602
- };
57
+ get: operations["searchBooks"];
58
+ put?: never;
59
+ post?: never;
60
+ delete?: never;
61
+ options?: never;
62
+ head?: never;
63
+ patch?: never;
64
+ trace?: never;
65
+ };
66
+ "/v3/books/{isbn}": {
67
+ parameters: {
68
+ query?: never;
69
+ header?: never;
70
+ path?: never;
71
+ cookie?: never;
603
72
  };
73
+ /** Get book by ISBN */
74
+ get: operations["getBookByISBN"];
604
75
  put?: never;
605
76
  post?: never;
606
77
  delete?: never;
@@ -609,377 +80,79 @@ export interface paths {
609
80
  patch?: never;
610
81
  trace?: never;
611
82
  };
612
- "/v1/search/title": {
83
+ "/v3/books/enrich": {
84
+ parameters: {
85
+ query?: never;
86
+ header?: never;
87
+ path?: never;
88
+ cookie?: never;
89
+ };
90
+ get?: never;
91
+ put?: never;
92
+ /** Enrich books with metadata */
93
+ post: operations["enrichBooks"];
94
+ delete?: never;
95
+ options?: never;
96
+ head?: never;
97
+ patch?: never;
98
+ trace?: never;
99
+ };
100
+ "/v3/jobs/imports": {
613
101
  parameters: {
614
102
  query?: never;
615
103
  header?: never;
616
104
  path?: never;
617
105
  cookie?: never;
618
106
  };
107
+ get?: never;
108
+ put?: never;
619
109
  /**
620
- * Search for books by title
621
- * @description Search for books by title using multi-provider orchestration.
622
- *
623
- * Returns up to 20 results by default, each including:
624
- * - Works: Abstract creative works (title, description, subjects)
625
- * - Editions: Physical/digital editions (publisher, publication date, format)
626
- * - Authors: Author biographical data (name, gender, cultural region)
627
- *
628
- * **Example:** `GET /v1/search/title?q=harry%20potter&limit=10`
629
- *
630
- * **Multi-Provider Orchestration:**
631
- * 1. OpenLibrary API - primary source for title searches
632
- * 2. Author enrichment from Wikidata (cultural diversity data)
633
- * 3. No caching (freshness important for search results)
634
- *
635
- * **Query Parameters:**
636
- * - `q` (required): Search query string (1-200 characters)
637
- * - `limit` (optional): Maximum number of results (1-100, default: 20)
638
- *
639
- * **Rate Limits:**
640
- * - 100 requests/minute per IP
641
- * - 1000 requests/hour per IP
642
- *
643
- * **Author Enrichment:**
644
- * All author results are enriched with cultural and biographical data from Wikidata.
110
+ * Import books from CSV
111
+ * @description Upload CSV file for background processing with Gemini 2.0 Flash. Returns immediately with jobId for progress tracking via SSE stream. Max file size: 8MB. Max rows: ~5000 books.
645
112
  */
646
- get: {
647
- parameters: {
648
- query: {
649
- /** @description Book title search query */
650
- q: string;
651
- /** @description Maximum number of results (1-100, default: 20) */
652
- limit?: string;
653
- };
654
- header?: never;
655
- path?: never;
656
- cookie?: never;
657
- };
658
- requestBody?: never;
659
- responses: {
660
- /** @description Books found successfully (may be empty if no matches) */
661
- 200: {
662
- headers: {
663
- [name: string]: unknown;
664
- };
665
- content: {
666
- /**
667
- * @example {
668
- * "data": {
669
- * "works": [
670
- * {
671
- * "title": "Harry Potter and the Philosopher's Stone",
672
- * "subjectTags": [
673
- * "magic",
674
- * "wizards",
675
- * "fantasy",
676
- * "adventure"
677
- * ],
678
- * "firstPublicationYear": 1997,
679
- * "description": "Harry Potter has never even heard of Hogwarts...",
680
- * "coverImageURL": "https://covers.openlibrary.org/b/id/12345-L.jpg",
681
- * "primaryProvider": "open_library",
682
- * "goodreadsWorkIDs": [
683
- * "OL82563W"
684
- * ],
685
- * "amazonASINs": [
686
- * "B0192CTMYG"
687
- * ],
688
- * "librarythingIDs": [],
689
- * "googleBooksVolumeIDs": [],
690
- * "isbndbQuality": 85,
691
- * "reviewStatus": "verified",
692
- * "synthetic": false
693
- * },
694
- * {
695
- * "title": "Harry Potter and the Chamber of Secrets",
696
- * "subjectTags": [
697
- * "magic",
698
- * "wizards",
699
- * "fantasy"
700
- * ],
701
- * "firstPublicationYear": 1998,
702
- * "description": "The summer after his first year at Hogwarts...",
703
- * "coverImageURL": "https://covers.openlibrary.org/b/id/12346-L.jpg",
704
- * "primaryProvider": "open_library",
705
- * "goodreadsWorkIDs": [
706
- * "OL82563W"
707
- * ],
708
- * "amazonASINs": [
709
- * "B0192CTNYH"
710
- * ],
711
- * "librarythingIDs": [],
712
- * "googleBooksVolumeIDs": [],
713
- * "isbndbQuality": 85,
714
- * "reviewStatus": "verified",
715
- * "synthetic": false
716
- * }
717
- * ],
718
- * "editions": [
719
- * {
720
- * "isbns": [
721
- * "9780439708180",
722
- * "0439708184"
723
- * ],
724
- * "title": "Harry Potter and the Philosopher's Stone",
725
- * "publisher": "Scholastic Inc.",
726
- * "publicationDate": "1999-09-01",
727
- * "pageCount": 309,
728
- * "format": "paperback",
729
- * "coverImageURL": "https://covers.openlibrary.org/b/isbn/9780439708180-L.jpg",
730
- * "primaryProvider": "open_library",
731
- * "amazonASINs": [
732
- * "0439708184"
733
- * ],
734
- * "googleBooksVolumeIDs": [],
735
- * "librarythingIDs": [],
736
- * "isbndbQuality": 85
737
- * }
738
- * ],
739
- * "authors": [
740
- * {
741
- * "name": "J.K. Rowling",
742
- * "gender": "female",
743
- * "culturalRegion": "europe",
744
- * "nationality": "British",
745
- * "birthYear": 1965,
746
- * "openLibraryID": "OL23919A",
747
- * "bookCount": 42
748
- * }
749
- * ],
750
- * "resultCount": 2
751
- * },
752
- * "metadata": {
753
- * "timestamp": "2025-11-28T12:00:00.000Z",
754
- * "processingTime": 1205,
755
- * "provider": "open_library",
756
- * "cached": false
757
- * }
758
- * }
759
- */
760
- "application/json": {
761
- data: {
762
- works: {
763
- title: string;
764
- subjectTags: string[];
765
- originalLanguage?: string;
766
- firstPublicationYear?: number;
767
- description?: string;
768
- /** Format: uri */
769
- coverImageURL?: string;
770
- synthetic?: boolean;
771
- /** @enum {string} */
772
- primaryProvider?: "google_books" | "open_library" | "isbndb" | "kv_cache";
773
- contributors?: ("google_books" | "open_library" | "isbndb" | "kv_cache")[];
774
- openLibraryID?: string;
775
- openLibraryWorkID?: string;
776
- isbndbID?: string;
777
- googleBooksVolumeID?: string;
778
- goodreadsID?: string;
779
- goodreadsWorkIDs: string[];
780
- amazonASINs: string[];
781
- librarythingIDs: string[];
782
- googleBooksVolumeIDs: string[];
783
- /** Format: date-time */
784
- lastISBNDBSync?: string;
785
- isbndbQuality: number;
786
- /** @enum {string} */
787
- reviewStatus: "unverified" | "verified" | "rejected" | "flagged";
788
- originalImagePath?: string;
789
- boundingBox?: {
790
- x: number;
791
- y: number;
792
- width: number;
793
- height: number;
794
- };
795
- }[];
796
- editions: {
797
- isbn?: string;
798
- isbns: string[];
799
- title?: string;
800
- publisher?: string;
801
- publicationDate?: string;
802
- pageCount?: number;
803
- /** @enum {string} */
804
- format: "hardcover" | "paperback" | "ebook" | "audiobook" | "mass_market" | "board_book" | "unknown";
805
- /** Format: uri */
806
- coverImageURL?: string;
807
- editionTitle?: string;
808
- editionDescription?: string;
809
- language?: string;
810
- /** @enum {string} */
811
- primaryProvider?: "google_books" | "open_library" | "isbndb" | "kv_cache";
812
- contributors?: ("google_books" | "open_library" | "isbndb" | "kv_cache")[];
813
- openLibraryID?: string;
814
- openLibraryEditionID?: string;
815
- isbndbID?: string;
816
- googleBooksVolumeID?: string;
817
- goodreadsID?: string;
818
- amazonASINs: string[];
819
- googleBooksVolumeIDs: string[];
820
- librarythingIDs: string[];
821
- /** Format: date-time */
822
- lastISBNDBSync?: string;
823
- isbndbQuality: number;
824
- }[];
825
- authors: {
826
- name: string;
827
- /** @enum {string} */
828
- gender: "male" | "female" | "non_binary" | "unknown";
829
- /** @enum {string} */
830
- culturalRegion?: "north_america" | "latin_america" | "europe" | "asia" | "africa" | "middle_east" | "oceania" | "unknown";
831
- nationality?: string;
832
- birthYear?: number;
833
- deathYear?: number;
834
- openLibraryID?: string;
835
- isbndbID?: string;
836
- googleBooksID?: string;
837
- goodreadsID?: string;
838
- bookCount?: number;
839
- }[];
840
- resultCount: number;
841
- };
842
- metadata?: {
843
- /** Format: date-time */
844
- timestamp: string;
845
- processingTime?: number;
846
- /** @enum {string} */
847
- provider?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "none";
848
- cached?: boolean;
849
- };
850
- };
851
- };
852
- };
853
- /** @description Invalid query parameters */
854
- 400: {
855
- headers: {
856
- [name: string]: unknown;
857
- };
858
- content: {
859
- /**
860
- * @example {
861
- * "data": null,
862
- * "metadata": {
863
- * "timestamp": "2025-11-28T12:00:00.000Z"
864
- * },
865
- * "error": {
866
- * "code": "INVALID_QUERY",
867
- * "message": "Search query is required and must be 1-200 characters",
868
- * "details": {
869
- * "parameter": "q"
870
- * }
871
- * }
872
- * }
873
- */
874
- "application/json": {
875
- data: unknown;
876
- metadata?: {
877
- /** Format: date-time */
878
- timestamp: string;
879
- cached?: boolean;
880
- /** @enum {string} */
881
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
882
- };
883
- error: {
884
- /** @enum {string} */
885
- code: "NOT_FOUND" | "INVALID_REQUEST" | "INVALID_ISBN" | "INVALID_QUERY" | "MISSING_PARAMETER" | "UNAUTHORIZED" | "FORBIDDEN" | "INTERNAL_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "RATE_LIMIT_EXCEEDED" | "CIRCUIT_OPEN" | "PROVIDER_ERROR" | "TIMEOUT";
886
- message: string;
887
- details?: {
888
- [key: string]: unknown;
889
- };
890
- retryable?: boolean;
891
- retryAfterMs?: number;
892
- provider?: string;
893
- };
894
- };
895
- };
896
- };
897
- /** @description Rate limit exceeded */
898
- 429: {
899
- headers: {
900
- [name: string]: unknown;
901
- };
902
- content: {
903
- /**
904
- * @example {
905
- * "data": null,
906
- * "metadata": {
907
- * "timestamp": "2025-11-28T12:00:00.000Z"
908
- * },
909
- * "error": {
910
- * "code": "RATE_LIMIT_EXCEEDED",
911
- * "message": "Rate limit exceeded. Maximum 100 requests per minute.",
912
- * "retryable": true,
913
- * "retryAfterMs": 60000
914
- * }
915
- * }
916
- */
917
- "application/json": {
918
- data: unknown;
919
- metadata?: {
920
- /** Format: date-time */
921
- timestamp: string;
922
- cached?: boolean;
923
- /** @enum {string} */
924
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
925
- };
926
- error: {
927
- /** @enum {string} */
928
- code: "NOT_FOUND" | "INVALID_REQUEST" | "INVALID_ISBN" | "INVALID_QUERY" | "MISSING_PARAMETER" | "UNAUTHORIZED" | "FORBIDDEN" | "INTERNAL_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "RATE_LIMIT_EXCEEDED" | "CIRCUIT_OPEN" | "PROVIDER_ERROR" | "TIMEOUT";
929
- message: string;
930
- details?: {
931
- [key: string]: unknown;
932
- };
933
- retryable?: boolean;
934
- retryAfterMs?: number;
935
- provider?: string;
936
- };
937
- };
938
- };
939
- };
940
- /** @description Internal server error */
941
- 500: {
942
- headers: {
943
- [name: string]: unknown;
944
- };
945
- content: {
946
- /**
947
- * @example {
948
- * "data": null,
949
- * "metadata": {
950
- * "timestamp": "2025-11-28T12:00:00.000Z"
951
- * },
952
- * "error": {
953
- * "code": "INTERNAL_ERROR",
954
- * "message": "An unexpected error occurred while processing the request"
955
- * }
956
- * }
957
- */
958
- "application/json": {
959
- data: unknown;
960
- metadata?: {
961
- /** Format: date-time */
962
- timestamp: string;
963
- cached?: boolean;
964
- /** @enum {string} */
965
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
966
- };
967
- error: {
968
- /** @enum {string} */
969
- code: "NOT_FOUND" | "INVALID_REQUEST" | "INVALID_ISBN" | "INVALID_QUERY" | "MISSING_PARAMETER" | "UNAUTHORIZED" | "FORBIDDEN" | "INTERNAL_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "RATE_LIMIT_EXCEEDED" | "CIRCUIT_OPEN" | "PROVIDER_ERROR" | "TIMEOUT";
970
- message: string;
971
- details?: {
972
- [key: string]: unknown;
973
- };
974
- retryable?: boolean;
975
- retryAfterMs?: number;
976
- provider?: string;
977
- };
978
- };
979
- };
980
- };
981
- };
113
+ post: operations["createImportJob"];
114
+ delete?: never;
115
+ options?: never;
116
+ head?: never;
117
+ patch?: never;
118
+ trace?: never;
119
+ };
120
+ "/v3/jobs/imports/{jobId}": {
121
+ parameters: {
122
+ query?: never;
123
+ header?: never;
124
+ path?: never;
125
+ cookie?: never;
126
+ };
127
+ /**
128
+ * Get import job status
129
+ * @description Query current status of CSV import job. Use SSE stream for real-time updates (recommended). Polling fallback: max 1 request every 2 seconds.
130
+ */
131
+ get: operations["getImportJobStatus"];
132
+ put?: never;
133
+ post?: never;
134
+ /**
135
+ * Cancel import job
136
+ * @description Cancel in-progress import job. Note: Jobs may not stop immediately (graceful shutdown).
137
+ */
138
+ delete: operations["cancelImportJob"];
139
+ options?: never;
140
+ head?: never;
141
+ patch?: never;
142
+ trace?: never;
143
+ };
144
+ "/v3/jobs/imports/{jobId}/stream": {
145
+ parameters: {
146
+ query?: never;
147
+ header?: never;
148
+ path?: never;
149
+ cookie?: never;
982
150
  };
151
+ /**
152
+ * Stream import progress (SSE)
153
+ * @description Real-time progress updates via Server-Sent Events. Requires Bearer token from job creation response. Token valid for 1 hour.
154
+ */
155
+ get: operations["streamImportProgress"];
983
156
  put?: never;
984
157
  post?: never;
985
158
  delete?: never;
@@ -988,7 +161,7 @@ export interface paths {
988
161
  patch?: never;
989
162
  trace?: never;
990
163
  };
991
- "/api/v2/capabilities": {
164
+ "/v3/jobs/imports/{jobId}/results": {
992
165
  parameters: {
993
166
  query?: never;
994
167
  header?: never;
@@ -996,98 +169,158 @@ export interface paths {
996
169
  cookie?: never;
997
170
  };
998
171
  /**
999
- * Get API capabilities and feature availability
1000
- * @description Returns comprehensive feature availability and configuration.
1001
- * Clients should call this on app startup to discover available features.
1002
- *
1003
- * **Use Cases:**
1004
- * - Feature discovery (check which endpoints are available)
1005
- * - Version compatibility (check API version)
1006
- * - Rate limit awareness (know limits before hitting them)
1007
- * - Deprecation notices (prepare for sunset endpoints)
172
+ * Get import job results
173
+ * @description Fetch enriched books from completed import job. Results cached in KV for 1 hour after completion.
1008
174
  */
1009
- get: {
1010
- parameters: {
1011
- query?: never;
1012
- header?: never;
1013
- path?: never;
1014
- cookie?: never;
1015
- };
1016
- requestBody?: never;
1017
- responses: {
1018
- /** @description API capabilities retrieved successfully */
1019
- 200: {
1020
- headers: {
1021
- [name: string]: unknown;
1022
- };
1023
- content: {
1024
- "application/json": {
1025
- data: {
1026
- apiVersion: string;
1027
- features: {
1028
- name: string;
1029
- enabled: boolean;
1030
- version: string;
1031
- endpoints: string[];
1032
- rateLimit?: {
1033
- requests: number;
1034
- windowMs: number;
1035
- };
1036
- notes?: string;
1037
- }[];
1038
- limits: {
1039
- maxBatchSize: number;
1040
- maxCsvRows: number;
1041
- maxImageSizeMb: number;
1042
- maxConcurrentJobs: number;
1043
- };
1044
- deprecations: {
1045
- endpoint: string;
1046
- sunsetDate: string;
1047
- replacement: string;
1048
- }[];
1049
- };
1050
- metadata?: {
1051
- /** Format: date-time */
1052
- timestamp: string;
1053
- cached?: boolean;
1054
- /** @enum {string} */
1055
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
1056
- };
1057
- };
1058
- };
1059
- };
1060
- /** @description Internal server error */
1061
- 500: {
1062
- headers: {
1063
- [name: string]: unknown;
1064
- };
1065
- content: {
1066
- "application/json": {
1067
- data: unknown;
1068
- metadata?: {
1069
- /** Format: date-time */
1070
- timestamp: string;
1071
- cached?: boolean;
1072
- /** @enum {string} */
1073
- source?: "google_books" | "open_library" | "isbndb" | "kv_cache" | "d1_database" | "vectorize";
1074
- };
1075
- error: {
1076
- /** @enum {string} */
1077
- code: "NOT_FOUND" | "INVALID_REQUEST" | "INVALID_ISBN" | "INVALID_QUERY" | "MISSING_PARAMETER" | "UNAUTHORIZED" | "FORBIDDEN" | "INTERNAL_ERROR" | "API_ERROR" | "NETWORK_ERROR" | "RATE_LIMIT_EXCEEDED" | "CIRCUIT_OPEN" | "PROVIDER_ERROR" | "TIMEOUT";
1078
- message: string;
1079
- details?: {
1080
- [key: string]: unknown;
1081
- };
1082
- retryable?: boolean;
1083
- retryAfterMs?: number;
1084
- provider?: string;
1085
- };
1086
- };
1087
- };
1088
- };
1089
- };
175
+ get: operations["getImportJobResults"];
176
+ put?: never;
177
+ post?: never;
178
+ delete?: never;
179
+ options?: never;
180
+ head?: never;
181
+ patch?: never;
182
+ trace?: never;
183
+ };
184
+ "/v3/jobs/scans": {
185
+ parameters: {
186
+ query?: never;
187
+ header?: never;
188
+ path?: never;
189
+ cookie?: never;
190
+ };
191
+ get?: never;
192
+ put?: never;
193
+ /**
194
+ * Scan bookshelf photos
195
+ * @description Upload 1-5 photos for AI-powered book detection with Gemini Vision. Returns immediately with jobId for progress tracking via SSE stream. Max size: 10MB per photo, 50MB total.
196
+ */
197
+ post: operations["createScanJob"];
198
+ delete?: never;
199
+ options?: never;
200
+ head?: never;
201
+ patch?: never;
202
+ trace?: never;
203
+ };
204
+ "/v3/jobs/scans/{jobId}": {
205
+ parameters: {
206
+ query?: never;
207
+ header?: never;
208
+ path?: never;
209
+ cookie?: never;
210
+ };
211
+ /**
212
+ * Get scan job status
213
+ * @description Query current status of bookshelf scan job. Use SSE stream for real-time updates (recommended). Polling fallback: max 1 request every 2 seconds.
214
+ */
215
+ get: operations["getScanJobStatus"];
216
+ put?: never;
217
+ post?: never;
218
+ /**
219
+ * Cancel scan job
220
+ * @description Cancel in-progress scan job and cleanup R2 storage. Deletes all uploaded photos for this job. Note: Jobs may not stop immediately (graceful shutdown).
221
+ */
222
+ delete: operations["cancelScanJob"];
223
+ options?: never;
224
+ head?: never;
225
+ patch?: never;
226
+ trace?: never;
227
+ };
228
+ "/v3/jobs/scans/{jobId}/stream": {
229
+ parameters: {
230
+ query?: never;
231
+ header?: never;
232
+ path?: never;
233
+ cookie?: never;
234
+ };
235
+ /**
236
+ * Stream scan progress (SSE)
237
+ * @description Real-time progress updates via Server-Sent Events. Requires Bearer token from job creation response. Token valid for 1 hour.
238
+ */
239
+ get: operations["streamScanProgress"];
240
+ put?: never;
241
+ post?: never;
242
+ delete?: never;
243
+ options?: never;
244
+ head?: never;
245
+ patch?: never;
246
+ trace?: never;
247
+ };
248
+ "/v3/jobs/scans/{jobId}/results": {
249
+ parameters: {
250
+ query?: never;
251
+ header?: never;
252
+ path?: never;
253
+ cookie?: never;
254
+ };
255
+ /**
256
+ * Get scan job results
257
+ * @description Fetch detected books from completed scan job. Results include book metadata, bounding boxes, confidence scores, and enrichment data. Results cached in KV for 2 hours after completion.
258
+ */
259
+ get: operations["getScanJobResults"];
260
+ put?: never;
261
+ post?: never;
262
+ delete?: never;
263
+ options?: never;
264
+ head?: never;
265
+ patch?: never;
266
+ trace?: never;
267
+ };
268
+ "/v3/jobs/enrichment/{jobId}": {
269
+ parameters: {
270
+ query?: never;
271
+ header?: never;
272
+ path?: never;
273
+ cookie?: never;
274
+ };
275
+ /**
276
+ * Get enrichment job status
277
+ * @description Query current status of batch enrichment job. Use SSE stream for real-time updates (recommended). Polling fallback: max 1 request every 2 seconds.
278
+ */
279
+ get: operations["getEnrichmentJobStatus"];
280
+ put?: never;
281
+ post?: never;
282
+ /**
283
+ * Cancel enrichment job
284
+ * @description Cancel in-progress enrichment job. Note: Jobs may not stop immediately (graceful shutdown).
285
+ */
286
+ delete: operations["cancelEnrichmentJob"];
287
+ options?: never;
288
+ head?: never;
289
+ patch?: never;
290
+ trace?: never;
291
+ };
292
+ "/v3/jobs/enrichment/{jobId}/stream": {
293
+ parameters: {
294
+ query?: never;
295
+ header?: never;
296
+ path?: never;
297
+ cookie?: never;
298
+ };
299
+ /**
300
+ * Stream enrichment progress (SSE)
301
+ * @description Real-time progress updates via Server-Sent Events. Progress updates every 25 books. Requires Bearer token from job creation response. Token valid for 1 hour.
302
+ */
303
+ get: operations["streamEnrichmentProgress"];
304
+ put?: never;
305
+ post?: never;
306
+ delete?: never;
307
+ options?: never;
308
+ head?: never;
309
+ patch?: never;
310
+ trace?: never;
311
+ };
312
+ "/v3/jobs/enrichment/{jobId}/results": {
313
+ parameters: {
314
+ query?: never;
315
+ header?: never;
316
+ path?: never;
317
+ cookie?: never;
1090
318
  };
319
+ /**
320
+ * Get enrichment job results
321
+ * @description Fetch enriched books from completed enrichment job. Results include enriched book metadata, books that were not found, and embedding generation status. Results cached in KV for 2 hours after completion.
322
+ */
323
+ get: operations["getEnrichmentJobResults"];
1091
324
  put?: never;
1092
325
  post?: never;
1093
326
  delete?: never;
@@ -1096,16 +329,995 @@ export interface paths {
1096
329
  patch?: never;
1097
330
  trace?: never;
1098
331
  };
332
+ "/v3/webhooks/alexandria/enrichment-complete": {
333
+ parameters: {
334
+ query?: never;
335
+ header?: never;
336
+ path?: never;
337
+ cookie?: never;
338
+ };
339
+ get?: never;
340
+ put?: never;
341
+ /**
342
+ * Handle enrichment completion event
343
+ * @description Receives notification from Alexandria when book enrichment is complete. Triggers a fresh fetch to update local D1 cache.
344
+ */
345
+ post: operations["alexandriaEnrichmentComplete"];
346
+ delete?: never;
347
+ options?: never;
348
+ head?: never;
349
+ patch?: never;
350
+ trace?: never;
351
+ };
1099
352
  }
1100
353
  export type webhooks = Record<string, never>;
1101
354
  export interface components {
1102
- schemas: never;
1103
- responses: never;
1104
- parameters: never;
1105
- requestBodies: never;
1106
- headers: never;
1107
- pathItems: never;
1108
- }
1109
- export type $defs = Record<string, never>;
1110
- export type operations = Record<string, never>;
355
+ schemas: {
356
+ SearchResponse: {
357
+ success: boolean;
358
+ data: {
359
+ books?: components["schemas"]["Book"][];
360
+ total?: number;
361
+ };
362
+ metadata: components["schemas"]["ResponseMetadata"];
363
+ };
364
+ BookResponse: {
365
+ success: boolean;
366
+ data: components["schemas"]["Book"];
367
+ metadata: components["schemas"]["ResponseMetadata"];
368
+ };
369
+ EnrichRequest: {
370
+ isbns: string[];
371
+ /** @default false */
372
+ includeEmbedding: boolean;
373
+ };
374
+ EnrichResponse: {
375
+ success: boolean;
376
+ data: {
377
+ books?: components["schemas"]["Book"][];
378
+ found?: number;
379
+ requested?: number;
380
+ };
381
+ metadata: components["schemas"]["ResponseMetadata"];
382
+ };
383
+ Book: {
384
+ /** @description 13-digit ISBN (example: 9780439708180) */
385
+ isbn: string;
386
+ /** @description 10-digit ISBN if available (example: 0439708184) */
387
+ isbn10?: string;
388
+ /** @description Book title */
389
+ title: string;
390
+ /** @description Book subtitle */
391
+ subtitle?: string;
392
+ /** @description List of author names */
393
+ authors: string[];
394
+ /** @description Publisher name */
395
+ publisher?: string;
396
+ /** @description Publication date (ISO 8601 or partial format) */
397
+ publishedDate?: string;
398
+ /** @description Book description/synopsis */
399
+ description?: string;
400
+ /** @description Number of pages */
401
+ pageCount?: number;
402
+ /** @description Book categories/genres */
403
+ categories?: string[];
404
+ /** @description ISO 639-1 language code (e.g., "en") */
405
+ language?: string;
406
+ /**
407
+ * Format: uri
408
+ * @description Cover image URL
409
+ */
410
+ coverUrl?: string;
411
+ /**
412
+ * Format: uri
413
+ * @description Thumbnail image URL
414
+ */
415
+ thumbnailUrl?: string;
416
+ /** @description OpenLibrary work key (e.g., OL82563W) */
417
+ workKey?: string;
418
+ /** @description OpenLibrary edition key (e.g., OL7353617M) */
419
+ editionKey?: string;
420
+ /**
421
+ * @description Data source provider
422
+ * @enum {string}
423
+ */
424
+ provider: "alexandria" | "google_books" | "open_library" | "isbndb";
425
+ /** @description Data quality score 0-100 */
426
+ quality: number;
427
+ };
428
+ ErrorResponse: {
429
+ /** @enum {boolean} */
430
+ success: false;
431
+ error: {
432
+ code: string;
433
+ message: string;
434
+ retryable?: boolean;
435
+ };
436
+ };
437
+ ResponseMetadata: {
438
+ /** Format: date-time */
439
+ timestamp: string;
440
+ requestId?: string;
441
+ cached?: boolean;
442
+ /** @description Request processing time in milliseconds */
443
+ processingTime?: number;
444
+ };
445
+ /** @description API capabilities (iOS-compatible flat format) */
446
+ CapabilitiesResponse: {
447
+ features: components["schemas"]["CapabilitiesFeatures"];
448
+ limits: components["schemas"]["CapabilitiesLimits"];
449
+ /** @description API version */
450
+ version: string;
451
+ };
452
+ CapabilitiesFeatures: {
453
+ /** @description Semantic search enabled */
454
+ semantic_search: boolean;
455
+ /** @description Similar books search enabled */
456
+ similar_books: boolean;
457
+ /** @description Weekly recommendations enabled */
458
+ weekly_recommendations: boolean;
459
+ /** @description SSE streaming enabled */
460
+ sse_streaming: boolean;
461
+ /** @description Batch enrichment enabled */
462
+ batch_enrichment: boolean;
463
+ /** @description CSV import enabled */
464
+ csv_import: boolean;
465
+ };
466
+ CapabilitiesLimits: {
467
+ /** @description Semantic search requests per minute */
468
+ semantic_search_rpm: number;
469
+ /** @description Text search requests per minute */
470
+ text_search_rpm: number;
471
+ /** @description Maximum rows in CSV import */
472
+ csv_max_rows: number;
473
+ /** @description Maximum photos in batch scan */
474
+ batch_max_photos: number;
475
+ };
476
+ RecommendationsResponse: {
477
+ success: boolean;
478
+ data: {
479
+ /** @description Week start date (ISO 8601) */
480
+ weekOf: string;
481
+ recommendations: components["schemas"]["Recommendation"][];
482
+ /** @description Number of recommendations returned */
483
+ count: number;
484
+ /** @description Total recommendations available */
485
+ totalAvailable: number;
486
+ };
487
+ metadata: components["schemas"]["ResponseMetadata"];
488
+ };
489
+ Recommendation: {
490
+ /** @description Book ISBN */
491
+ isbn: string;
492
+ /** @description Book title */
493
+ title: string;
494
+ /** @description Primary author */
495
+ author: string;
496
+ /**
497
+ * Format: uri
498
+ * @description Cover image URL
499
+ */
500
+ coverUrl?: string;
501
+ /** @description Why this book is recommended */
502
+ reason: string;
503
+ };
504
+ JobInitResponse: {
505
+ success: boolean;
506
+ data: {
507
+ /**
508
+ * Format: uuid
509
+ * @description Unique job identifier
510
+ */
511
+ jobId: string;
512
+ /**
513
+ * @description Initial job status (always 'queued')
514
+ * @enum {string}
515
+ */
516
+ status: "queued" | "processing" | "completed" | "failed" | "canceled";
517
+ /**
518
+ * Format: uri
519
+ * @description SSE stream URL for real-time progress
520
+ */
521
+ streamUrl: string;
522
+ /** @description Bearer token for SSE authentication (valid 1 hour) */
523
+ token: string;
524
+ };
525
+ metadata: components["schemas"]["ResponseMetadata"];
526
+ };
527
+ JobStatusResponse: {
528
+ success: boolean;
529
+ data: {
530
+ /** Format: uuid */
531
+ jobId: string;
532
+ /**
533
+ * @description Job type
534
+ * @enum {string}
535
+ */
536
+ type: "csv_import" | "bookshelf_scan" | "batch_enrichment";
537
+ /**
538
+ * @description Current job status
539
+ * @enum {string}
540
+ */
541
+ status: "queued" | "processing" | "completed" | "failed" | "canceled";
542
+ /** @description Progress as decimal (0.0 to 1.0) */
543
+ progress: number;
544
+ /** @description Items processed so far */
545
+ processedCount: number;
546
+ /** @description Total items to process */
547
+ totalCount: number;
548
+ /**
549
+ * Format: date-time
550
+ * @description Job start timestamp
551
+ */
552
+ startTime?: string;
553
+ /**
554
+ * Format: date-time
555
+ * @description Job completion timestamp
556
+ */
557
+ completedTime?: string;
558
+ /** @description Error details if job failed */
559
+ error?: {
560
+ code?: string;
561
+ message?: string;
562
+ };
563
+ };
564
+ metadata: components["schemas"]["ResponseMetadata"];
565
+ };
566
+ JobResultsResponse: {
567
+ success: boolean;
568
+ data: {
569
+ /** Format: uuid */
570
+ jobId: string;
571
+ /**
572
+ * @description Job status (only completed jobs have results)
573
+ * @enum {string}
574
+ */
575
+ status: "completed";
576
+ /** @description Job results (structure varies by job type) */
577
+ results: Record<string, never>[];
578
+ };
579
+ metadata: components["schemas"]["ResponseMetadata"];
580
+ };
581
+ };
582
+ responses: never;
583
+ parameters: never;
584
+ requestBodies: never;
585
+ headers: never;
586
+ pathItems: never;
587
+ }
588
+ export type $defs = Record<string, never>;
589
+ export interface operations {
590
+ getCapabilities: {
591
+ parameters: {
592
+ query?: never;
593
+ header?: never;
594
+ path?: never;
595
+ cookie?: never;
596
+ };
597
+ requestBody?: never;
598
+ responses: {
599
+ /** @description API capabilities */
600
+ 200: {
601
+ headers: {
602
+ [name: string]: unknown;
603
+ };
604
+ content: {
605
+ "application/json": components["schemas"]["CapabilitiesResponse"];
606
+ };
607
+ };
608
+ /** @description Server error */
609
+ 500: {
610
+ headers: {
611
+ [name: string]: unknown;
612
+ };
613
+ content: {
614
+ "application/problem+json": components["schemas"]["ErrorResponse"];
615
+ };
616
+ };
617
+ };
618
+ };
619
+ getWeeklyRecommendations: {
620
+ parameters: {
621
+ query?: {
622
+ /** @description Number of recommendations (1-20) */
623
+ limit?: number;
624
+ };
625
+ header?: never;
626
+ path?: never;
627
+ cookie?: never;
628
+ };
629
+ requestBody?: never;
630
+ responses: {
631
+ /** @description Weekly recommendations */
632
+ 200: {
633
+ headers: {
634
+ [name: string]: unknown;
635
+ };
636
+ content: {
637
+ "application/json": components["schemas"]["RecommendationsResponse"];
638
+ };
639
+ };
640
+ /** @description No recommendations available */
641
+ 404: {
642
+ headers: {
643
+ [name: string]: unknown;
644
+ };
645
+ content: {
646
+ "application/problem+json": components["schemas"]["ErrorResponse"];
647
+ };
648
+ };
649
+ /** @description Server error */
650
+ 500: {
651
+ headers: {
652
+ [name: string]: unknown;
653
+ };
654
+ content: {
655
+ "application/problem+json": components["schemas"]["ErrorResponse"];
656
+ };
657
+ };
658
+ };
659
+ };
660
+ searchBooks: {
661
+ parameters: {
662
+ query: {
663
+ /** @description Search query */
664
+ q: string;
665
+ mode?: "text" | "semantic" | "similar";
666
+ page?: number;
667
+ limit?: number;
668
+ };
669
+ header?: never;
670
+ path?: never;
671
+ cookie?: never;
672
+ };
673
+ requestBody?: never;
674
+ responses: {
675
+ /** @description Search results */
676
+ 200: {
677
+ headers: {
678
+ [name: string]: unknown;
679
+ };
680
+ content: {
681
+ "application/json": components["schemas"]["SearchResponse"];
682
+ };
683
+ };
684
+ /** @description Invalid request */
685
+ 400: {
686
+ headers: {
687
+ [name: string]: unknown;
688
+ };
689
+ content: {
690
+ "application/problem+json": components["schemas"]["ErrorResponse"];
691
+ };
692
+ };
693
+ };
694
+ };
695
+ getBookByISBN: {
696
+ parameters: {
697
+ query?: never;
698
+ header?: never;
699
+ path: {
700
+ isbn: string;
701
+ };
702
+ cookie?: never;
703
+ };
704
+ requestBody?: never;
705
+ responses: {
706
+ /** @description Book details */
707
+ 200: {
708
+ headers: {
709
+ [name: string]: unknown;
710
+ };
711
+ content: {
712
+ "application/json": components["schemas"]["BookResponse"];
713
+ };
714
+ };
715
+ /** @description Book not found */
716
+ 404: {
717
+ headers: {
718
+ [name: string]: unknown;
719
+ };
720
+ content: {
721
+ "application/problem+json": components["schemas"]["ErrorResponse"];
722
+ };
723
+ };
724
+ };
725
+ };
726
+ enrichBooks: {
727
+ parameters: {
728
+ query?: never;
729
+ header?: never;
730
+ path?: never;
731
+ cookie?: never;
732
+ };
733
+ requestBody: {
734
+ content: {
735
+ "application/json": components["schemas"]["EnrichRequest"];
736
+ };
737
+ };
738
+ responses: {
739
+ /** @description Enriched books */
740
+ 200: {
741
+ headers: {
742
+ [name: string]: unknown;
743
+ };
744
+ content: {
745
+ "application/json": components["schemas"]["EnrichResponse"];
746
+ };
747
+ };
748
+ };
749
+ };
750
+ createImportJob: {
751
+ parameters: {
752
+ query?: never;
753
+ header?: never;
754
+ path?: never;
755
+ cookie?: never;
756
+ };
757
+ requestBody: {
758
+ content: {
759
+ "multipart/form-data": {
760
+ /**
761
+ * Format: binary
762
+ * @description CSV file (max 8MB)
763
+ */
764
+ file: string;
765
+ };
766
+ };
767
+ };
768
+ responses: {
769
+ /** @description Import job accepted */
770
+ 202: {
771
+ headers: {
772
+ [name: string]: unknown;
773
+ };
774
+ content: {
775
+ "application/json": components["schemas"]["JobInitResponse"];
776
+ };
777
+ };
778
+ /** @description Invalid file (missing, wrong format) */
779
+ 400: {
780
+ headers: {
781
+ [name: string]: unknown;
782
+ };
783
+ content: {
784
+ "application/problem+json": components["schemas"]["ErrorResponse"];
785
+ };
786
+ };
787
+ /** @description File too large (>8MB) */
788
+ 413: {
789
+ headers: {
790
+ [name: string]: unknown;
791
+ };
792
+ content: {
793
+ "application/problem+json": components["schemas"]["ErrorResponse"];
794
+ };
795
+ };
796
+ };
797
+ };
798
+ getImportJobStatus: {
799
+ parameters: {
800
+ query?: never;
801
+ header?: never;
802
+ path: {
803
+ jobId: string;
804
+ };
805
+ cookie?: never;
806
+ };
807
+ requestBody?: never;
808
+ responses: {
809
+ /** @description Job status */
810
+ 200: {
811
+ headers: {
812
+ [name: string]: unknown;
813
+ };
814
+ content: {
815
+ "application/json": components["schemas"]["JobStatusResponse"];
816
+ };
817
+ };
818
+ /** @description Job not found */
819
+ 404: {
820
+ headers: {
821
+ [name: string]: unknown;
822
+ };
823
+ content: {
824
+ "application/problem+json": components["schemas"]["ErrorResponse"];
825
+ };
826
+ };
827
+ };
828
+ };
829
+ cancelImportJob: {
830
+ parameters: {
831
+ query?: never;
832
+ header?: never;
833
+ path: {
834
+ jobId: string;
835
+ };
836
+ cookie?: never;
837
+ };
838
+ requestBody?: never;
839
+ responses: {
840
+ /** @description Job canceled */
841
+ 200: {
842
+ headers: {
843
+ [name: string]: unknown;
844
+ };
845
+ content: {
846
+ "application/json": components["schemas"]["JobStatusResponse"];
847
+ };
848
+ };
849
+ /** @description Job not found */
850
+ 404: {
851
+ headers: {
852
+ [name: string]: unknown;
853
+ };
854
+ content: {
855
+ "application/problem+json": components["schemas"]["ErrorResponse"];
856
+ };
857
+ };
858
+ /** @description Job already completed or failed */
859
+ 409: {
860
+ headers: {
861
+ [name: string]: unknown;
862
+ };
863
+ content: {
864
+ "application/problem+json": components["schemas"]["ErrorResponse"];
865
+ };
866
+ };
867
+ };
868
+ };
869
+ streamImportProgress: {
870
+ parameters: {
871
+ query?: never;
872
+ header?: {
873
+ /** @description Bearer token from job creation */
874
+ Authorization?: string;
875
+ };
876
+ path: {
877
+ jobId: string;
878
+ };
879
+ cookie?: never;
880
+ };
881
+ requestBody?: never;
882
+ responses: {
883
+ /** @description SSE stream */
884
+ 200: {
885
+ headers: {
886
+ [name: string]: unknown;
887
+ };
888
+ content: {
889
+ "text/event-stream": Record<string, never>;
890
+ };
891
+ };
892
+ /** @description Unauthorized (invalid or expired token) */
893
+ 401: {
894
+ headers: {
895
+ [name: string]: unknown;
896
+ };
897
+ content: {
898
+ "application/problem+json": components["schemas"]["ErrorResponse"];
899
+ };
900
+ };
901
+ /** @description Job not found */
902
+ 404: {
903
+ headers: {
904
+ [name: string]: unknown;
905
+ };
906
+ content: {
907
+ "application/problem+json": components["schemas"]["ErrorResponse"];
908
+ };
909
+ };
910
+ };
911
+ };
912
+ getImportJobResults: {
913
+ parameters: {
914
+ query?: never;
915
+ header?: never;
916
+ path: {
917
+ jobId: string;
918
+ };
919
+ cookie?: never;
920
+ };
921
+ requestBody?: never;
922
+ responses: {
923
+ /** @description Job results */
924
+ 200: {
925
+ headers: {
926
+ [name: string]: unknown;
927
+ };
928
+ content: {
929
+ "application/json": components["schemas"]["JobResultsResponse"];
930
+ };
931
+ };
932
+ /** @description Job not found or not completed */
933
+ 404: {
934
+ headers: {
935
+ [name: string]: unknown;
936
+ };
937
+ content: {
938
+ "application/problem+json": components["schemas"]["ErrorResponse"];
939
+ };
940
+ };
941
+ };
942
+ };
943
+ createScanJob: {
944
+ parameters: {
945
+ query?: never;
946
+ header?: never;
947
+ path?: never;
948
+ cookie?: never;
949
+ };
950
+ requestBody: {
951
+ content: {
952
+ "multipart/form-data": {
953
+ /** @description Array of photo files (1-5 photos) */
954
+ "photos[]": string[];
955
+ };
956
+ };
957
+ };
958
+ responses: {
959
+ /** @description Scan job accepted */
960
+ 202: {
961
+ headers: {
962
+ [name: string]: unknown;
963
+ };
964
+ content: {
965
+ "application/json": components["schemas"]["JobInitResponse"];
966
+ };
967
+ };
968
+ /** @description Invalid request (missing photos, wrong format) */
969
+ 400: {
970
+ headers: {
971
+ [name: string]: unknown;
972
+ };
973
+ content: {
974
+ "application/problem+json": components["schemas"]["ErrorResponse"];
975
+ };
976
+ };
977
+ /** @description File too large (photo >10MB or batch >50MB) */
978
+ 413: {
979
+ headers: {
980
+ [name: string]: unknown;
981
+ };
982
+ content: {
983
+ "application/problem+json": components["schemas"]["ErrorResponse"];
984
+ };
985
+ };
986
+ };
987
+ };
988
+ getScanJobStatus: {
989
+ parameters: {
990
+ query?: never;
991
+ header?: never;
992
+ path: {
993
+ jobId: string;
994
+ };
995
+ cookie?: never;
996
+ };
997
+ requestBody?: never;
998
+ responses: {
999
+ /** @description Job status */
1000
+ 200: {
1001
+ headers: {
1002
+ [name: string]: unknown;
1003
+ };
1004
+ content: {
1005
+ "application/json": components["schemas"]["JobStatusResponse"];
1006
+ };
1007
+ };
1008
+ /** @description Job not found */
1009
+ 404: {
1010
+ headers: {
1011
+ [name: string]: unknown;
1012
+ };
1013
+ content: {
1014
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1015
+ };
1016
+ };
1017
+ };
1018
+ };
1019
+ cancelScanJob: {
1020
+ parameters: {
1021
+ query?: never;
1022
+ header?: never;
1023
+ path: {
1024
+ jobId: string;
1025
+ };
1026
+ cookie?: never;
1027
+ };
1028
+ requestBody?: never;
1029
+ responses: {
1030
+ /** @description Job canceled (includes R2 cleanup status) */
1031
+ 200: {
1032
+ headers: {
1033
+ [name: string]: unknown;
1034
+ };
1035
+ content: {
1036
+ "application/json": components["schemas"]["JobStatusResponse"];
1037
+ };
1038
+ };
1039
+ /** @description Job not found */
1040
+ 404: {
1041
+ headers: {
1042
+ [name: string]: unknown;
1043
+ };
1044
+ content: {
1045
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1046
+ };
1047
+ };
1048
+ /** @description Job already completed or failed */
1049
+ 409: {
1050
+ headers: {
1051
+ [name: string]: unknown;
1052
+ };
1053
+ content: {
1054
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1055
+ };
1056
+ };
1057
+ };
1058
+ };
1059
+ streamScanProgress: {
1060
+ parameters: {
1061
+ query?: never;
1062
+ header?: {
1063
+ /** @description Bearer token from job creation */
1064
+ Authorization?: string;
1065
+ };
1066
+ path: {
1067
+ jobId: string;
1068
+ };
1069
+ cookie?: never;
1070
+ };
1071
+ requestBody?: never;
1072
+ responses: {
1073
+ /** @description SSE stream */
1074
+ 200: {
1075
+ headers: {
1076
+ [name: string]: unknown;
1077
+ };
1078
+ content: {
1079
+ "text/event-stream": Record<string, never>;
1080
+ };
1081
+ };
1082
+ /** @description Unauthorized (invalid or expired token) */
1083
+ 401: {
1084
+ headers: {
1085
+ [name: string]: unknown;
1086
+ };
1087
+ content: {
1088
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1089
+ };
1090
+ };
1091
+ /** @description Job not found */
1092
+ 404: {
1093
+ headers: {
1094
+ [name: string]: unknown;
1095
+ };
1096
+ content: {
1097
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1098
+ };
1099
+ };
1100
+ };
1101
+ };
1102
+ getScanJobResults: {
1103
+ parameters: {
1104
+ query?: never;
1105
+ header?: never;
1106
+ path: {
1107
+ jobId: string;
1108
+ };
1109
+ cookie?: never;
1110
+ };
1111
+ requestBody?: never;
1112
+ responses: {
1113
+ /** @description Job results */
1114
+ 200: {
1115
+ headers: {
1116
+ [name: string]: unknown;
1117
+ };
1118
+ content: {
1119
+ "application/json": components["schemas"]["JobResultsResponse"];
1120
+ };
1121
+ };
1122
+ /** @description Job not found or not completed */
1123
+ 404: {
1124
+ headers: {
1125
+ [name: string]: unknown;
1126
+ };
1127
+ content: {
1128
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1129
+ };
1130
+ };
1131
+ };
1132
+ };
1133
+ getEnrichmentJobStatus: {
1134
+ parameters: {
1135
+ query?: never;
1136
+ header?: never;
1137
+ path: {
1138
+ jobId: string;
1139
+ };
1140
+ cookie?: never;
1141
+ };
1142
+ requestBody?: never;
1143
+ responses: {
1144
+ /** @description Job status */
1145
+ 200: {
1146
+ headers: {
1147
+ [name: string]: unknown;
1148
+ };
1149
+ content: {
1150
+ "application/json": components["schemas"]["JobStatusResponse"];
1151
+ };
1152
+ };
1153
+ /** @description Job not found */
1154
+ 404: {
1155
+ headers: {
1156
+ [name: string]: unknown;
1157
+ };
1158
+ content: {
1159
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1160
+ };
1161
+ };
1162
+ };
1163
+ };
1164
+ cancelEnrichmentJob: {
1165
+ parameters: {
1166
+ query?: never;
1167
+ header?: never;
1168
+ path: {
1169
+ jobId: string;
1170
+ };
1171
+ cookie?: never;
1172
+ };
1173
+ requestBody?: never;
1174
+ responses: {
1175
+ /** @description Job canceled */
1176
+ 200: {
1177
+ headers: {
1178
+ [name: string]: unknown;
1179
+ };
1180
+ content: {
1181
+ "application/json": components["schemas"]["JobStatusResponse"];
1182
+ };
1183
+ };
1184
+ /** @description Job not found */
1185
+ 404: {
1186
+ headers: {
1187
+ [name: string]: unknown;
1188
+ };
1189
+ content: {
1190
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1191
+ };
1192
+ };
1193
+ /** @description Job already completed or failed */
1194
+ 409: {
1195
+ headers: {
1196
+ [name: string]: unknown;
1197
+ };
1198
+ content: {
1199
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1200
+ };
1201
+ };
1202
+ };
1203
+ };
1204
+ streamEnrichmentProgress: {
1205
+ parameters: {
1206
+ query?: never;
1207
+ header?: {
1208
+ /** @description Bearer token from job creation */
1209
+ Authorization?: string;
1210
+ };
1211
+ path: {
1212
+ jobId: string;
1213
+ };
1214
+ cookie?: never;
1215
+ };
1216
+ requestBody?: never;
1217
+ responses: {
1218
+ /** @description SSE stream */
1219
+ 200: {
1220
+ headers: {
1221
+ [name: string]: unknown;
1222
+ };
1223
+ content: {
1224
+ "text/event-stream": Record<string, never>;
1225
+ };
1226
+ };
1227
+ /** @description Unauthorized (invalid or expired token) */
1228
+ 401: {
1229
+ headers: {
1230
+ [name: string]: unknown;
1231
+ };
1232
+ content: {
1233
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1234
+ };
1235
+ };
1236
+ /** @description Job not found */
1237
+ 404: {
1238
+ headers: {
1239
+ [name: string]: unknown;
1240
+ };
1241
+ content: {
1242
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1243
+ };
1244
+ };
1245
+ };
1246
+ };
1247
+ getEnrichmentJobResults: {
1248
+ parameters: {
1249
+ query?: never;
1250
+ header?: never;
1251
+ path: {
1252
+ jobId: string;
1253
+ };
1254
+ cookie?: never;
1255
+ };
1256
+ requestBody?: never;
1257
+ responses: {
1258
+ /** @description Job results */
1259
+ 200: {
1260
+ headers: {
1261
+ [name: string]: unknown;
1262
+ };
1263
+ content: {
1264
+ "application/json": components["schemas"]["JobResultsResponse"];
1265
+ };
1266
+ };
1267
+ /** @description Job not found or not completed */
1268
+ 404: {
1269
+ headers: {
1270
+ [name: string]: unknown;
1271
+ };
1272
+ content: {
1273
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1274
+ };
1275
+ };
1276
+ };
1277
+ };
1278
+ alexandriaEnrichmentComplete: {
1279
+ parameters: {
1280
+ query?: never;
1281
+ header: {
1282
+ /** @description Shared secret for authentication */
1283
+ "x-alexandria-webhook-secret": string;
1284
+ };
1285
+ path?: never;
1286
+ cookie?: never;
1287
+ };
1288
+ requestBody: {
1289
+ content: {
1290
+ "application/json": {
1291
+ isbn: string;
1292
+ /** @enum {string} */
1293
+ type: "edition" | "work" | "author";
1294
+ quality_improvement?: number;
1295
+ };
1296
+ };
1297
+ };
1298
+ responses: {
1299
+ /** @description Webhook processed successfully */
1300
+ 200: {
1301
+ headers: {
1302
+ [name: string]: unknown;
1303
+ };
1304
+ content: {
1305
+ "application/json": {
1306
+ success: boolean;
1307
+ message: string;
1308
+ };
1309
+ };
1310
+ };
1311
+ /** @description Invalid secret */
1312
+ 401: {
1313
+ headers: {
1314
+ [name: string]: unknown;
1315
+ };
1316
+ content: {
1317
+ "application/problem+json": components["schemas"]["ErrorResponse"];
1318
+ };
1319
+ };
1320
+ };
1321
+ };
1322
+ }
1111
1323
  //# sourceMappingURL=schema.d.ts.map