channel3-sdk 0.1.1__py3-none-any.whl → 0.1.12__py3-none-any.whl

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.

Potentially problematic release.


This version of channel3-sdk might be problematic. Click here for more details.

channel3_sdk/__init__.py CHANGED
@@ -6,8 +6,9 @@ from .models import (
6
6
  ProductDetail,
7
7
  SearchFilters,
8
8
  SearchRequest,
9
- MerchantOffering,
10
- FamilyMember,
9
+ SearchFilterPrice,
10
+ Brand,
11
+ Variant,
11
12
  Price,
12
13
  AvailabilityStatus,
13
14
  )
@@ -20,7 +21,7 @@ from .exceptions import (
20
21
  Channel3ConnectionError,
21
22
  )
22
23
 
23
- __version__ = "0.1.0"
24
+ __version__ = "0.2.0"
24
25
  __all__ = [
25
26
  # Clients
26
27
  "Channel3Client",
@@ -30,8 +31,9 @@ __all__ = [
30
31
  "ProductDetail",
31
32
  "SearchFilters",
32
33
  "SearchRequest",
33
- "MerchantOffering",
34
- "FamilyMember",
34
+ "SearchFilterPrice",
35
+ "Brand",
36
+ "Variant",
35
37
  "Price",
36
38
  "AvailabilityStatus",
37
39
  # Exceptions
channel3_sdk/client.py CHANGED
@@ -6,7 +6,7 @@ import aiohttp
6
6
  import asyncio
7
7
  from pydantic import ValidationError
8
8
 
9
- from .models import Product, ProductDetail, SearchFilters, SearchRequest
9
+ from .models import Product, ProductDetail, SearchFilters, SearchRequest, Brand
10
10
  from .exceptions import (
11
11
  Channel3Error,
12
12
  Channel3AuthenticationError,
@@ -127,7 +127,7 @@ class Channel3Client(BaseChannel3Client):
127
127
  query=query,
128
128
  image_url=image_url,
129
129
  base64_image=base64_image,
130
- filters=filters,
130
+ filters=filters or SearchFilters(),
131
131
  limit=limit,
132
132
  )
133
133
 
@@ -210,6 +210,119 @@ class Channel3Client(BaseChannel3Client):
210
210
  except ValidationError as e:
211
211
  raise Channel3Error(f"Invalid response format: {str(e)}")
212
212
 
213
+ def get_brands(
214
+ self,
215
+ query: Optional[str] = None,
216
+ page: int = 1,
217
+ size: int = 100,
218
+ ) -> List[Brand]:
219
+ """
220
+ Get all brands that the vendor currently sells.
221
+
222
+ Args:
223
+ query: Optional text query to filter brands
224
+ page: Page number for pagination (default: 1)
225
+ size: Number of brands per page (default: 100)
226
+
227
+ Returns:
228
+ List of Brand objects
229
+
230
+ Raises:
231
+ Channel3AuthenticationError: If API key is invalid
232
+ Channel3ValidationError: If request parameters are invalid
233
+ Channel3ServerError: If server encounters an error
234
+ Channel3ConnectionError: If there are connection issues
235
+
236
+ Example:
237
+ ```python
238
+ brands = client.get_brands()
239
+ for brand in brands:
240
+ print(f"Brand: {brand.name}")
241
+ ```
242
+ """
243
+ url = f"{self.base_url}/brands"
244
+ params = {}
245
+
246
+ if query is not None:
247
+ params["query"] = query
248
+ if page != 1:
249
+ params["page"] = page
250
+ if size != 100:
251
+ params["size"] = size
252
+
253
+ try:
254
+ response = requests.get(
255
+ url, headers=self.headers, params=params, timeout=30
256
+ )
257
+ response_data = response.json()
258
+
259
+ if response.status_code != 200:
260
+ self._handle_error_response(response.status_code, response_data, url)
261
+
262
+ # Parse and validate response
263
+ return [Brand(**item) for item in response_data]
264
+
265
+ except requests.exceptions.ConnectionError as e:
266
+ raise Channel3ConnectionError(
267
+ f"Failed to connect to Channel3 API: {str(e)}"
268
+ )
269
+ except requests.exceptions.Timeout as e:
270
+ raise Channel3ConnectionError(f"Request timed out: {str(e)}")
271
+ except requests.exceptions.RequestException as e:
272
+ raise Channel3Error(f"Request failed: {str(e)}")
273
+ except ValidationError as e:
274
+ raise Channel3Error(f"Invalid response format: {str(e)}")
275
+
276
+ def get_brand(self, brand_id: str) -> Brand:
277
+ """
278
+ Get detailed information for a specific brand by its ID.
279
+
280
+ Args:
281
+ brand_id: The unique identifier of the brand
282
+
283
+ Returns:
284
+ Brand object with detailed brand information
285
+
286
+ Raises:
287
+ Channel3AuthenticationError: If API key is invalid
288
+ Channel3NotFoundError: If brand is not found
289
+ Channel3ValidationError: If brand_id is invalid
290
+ Channel3ServerError: If server encounters an error
291
+ Channel3ConnectionError: If there are connection issues
292
+
293
+ Example:
294
+ ```python
295
+ brand = client.get_brand("brand_123456")
296
+ print(f"Brand: {brand.name}")
297
+ print(f"Description: {brand.description}")
298
+ ```
299
+ """
300
+ if not brand_id or not brand_id.strip():
301
+ raise ValueError("brand_id cannot be empty")
302
+
303
+ url = f"{self.base_url}/brands/{brand_id}"
304
+
305
+ try:
306
+ response = requests.get(url, headers=self.headers, timeout=30)
307
+ response_data = response.json()
308
+
309
+ if response.status_code != 200:
310
+ self._handle_error_response(response.status_code, response_data, url)
311
+
312
+ # Parse and validate response
313
+ return Brand(**response_data)
314
+
315
+ except requests.exceptions.ConnectionError as e:
316
+ raise Channel3ConnectionError(
317
+ f"Failed to connect to Channel3 API: {str(e)}"
318
+ )
319
+ except requests.exceptions.Timeout as e:
320
+ raise Channel3ConnectionError(f"Request timed out: {str(e)}")
321
+ except requests.exceptions.RequestException as e:
322
+ raise Channel3Error(f"Request failed: {str(e)}")
323
+ except ValidationError as e:
324
+ raise Channel3Error(f"Invalid response format: {str(e)}")
325
+
213
326
 
214
327
  class AsyncChannel3Client(BaseChannel3Client):
215
328
  """Asynchronous Channel3 API client."""
@@ -255,7 +368,7 @@ class AsyncChannel3Client(BaseChannel3Client):
255
368
  query=query,
256
369
  image_url=image_url,
257
370
  base64_image=base64_image,
258
- filters=filters,
371
+ filters=filters or SearchFilters(),
259
372
  limit=limit,
260
373
  )
261
374
 
@@ -339,3 +452,123 @@ class AsyncChannel3Client(BaseChannel3Client):
339
452
  raise Channel3Error(f"Request failed: {str(e)}")
340
453
  except ValidationError as e:
341
454
  raise Channel3Error(f"Invalid response format: {str(e)}")
455
+
456
+ async def get_brands(
457
+ self,
458
+ query: Optional[str] = None,
459
+ page: int = 1,
460
+ size: int = 100,
461
+ ) -> List[Brand]:
462
+ """
463
+ Get all brands that the vendor currently sells.
464
+
465
+ Args:
466
+ query: Optional text query to filter brands
467
+ page: Page number for pagination (default: 1)
468
+ size: Number of brands per page (default: 100)
469
+
470
+ Returns:
471
+ List of Brand objects
472
+
473
+ Raises:
474
+ Channel3AuthenticationError: If API key is invalid
475
+ Channel3ValidationError: If request parameters are invalid
476
+ Channel3ServerError: If server encounters an error
477
+ Channel3ConnectionError: If there are connection issues
478
+
479
+ Example:
480
+ ```python
481
+ brands = await async_client.get_brands()
482
+ for brand in brands:
483
+ print(f"Brand: {brand.name}")
484
+ ```
485
+ """
486
+ url = f"{self.base_url}/brands"
487
+ params = {}
488
+
489
+ if query is not None:
490
+ params["query"] = query
491
+ if page != 1:
492
+ params["page"] = page
493
+ if size != 100:
494
+ params["size"] = size
495
+
496
+ try:
497
+ async with aiohttp.ClientSession() as session:
498
+ async with session.get(
499
+ url,
500
+ headers=self.headers,
501
+ params=params,
502
+ timeout=aiohttp.ClientTimeout(total=30),
503
+ ) as response:
504
+ response_data = await response.json()
505
+
506
+ if response.status != 200:
507
+ self._handle_error_response(response.status, response_data, url)
508
+
509
+ # Parse and validate response
510
+ return [Brand(**item) for item in response_data]
511
+
512
+ except aiohttp.ClientConnectionError as e:
513
+ raise Channel3ConnectionError(
514
+ f"Failed to connect to Channel3 API: {str(e)}"
515
+ )
516
+ except asyncio.TimeoutError as e:
517
+ raise Channel3ConnectionError(f"Request timed out: {str(e)}")
518
+ except aiohttp.ClientError as e:
519
+ raise Channel3Error(f"Request failed: {str(e)}")
520
+ except ValidationError as e:
521
+ raise Channel3Error(f"Invalid response format: {str(e)}")
522
+
523
+ async def get_brand(self, brand_id: str) -> Brand:
524
+ """
525
+ Get detailed information for a specific brand by its ID.
526
+
527
+ Args:
528
+ brand_id: The unique identifier of the brand
529
+
530
+ Returns:
531
+ Brand object with detailed brand information
532
+
533
+ Raises:
534
+ Channel3AuthenticationError: If API key is invalid
535
+ Channel3NotFoundError: If brand is not found
536
+ Channel3ValidationError: If brand_id is invalid
537
+ Channel3ServerError: If server encounters an error
538
+ Channel3ConnectionError: If there are connection issues
539
+
540
+ Example:
541
+ ```python
542
+ brand = await async_client.get_brand("brand_123456")
543
+ print(f"Brand: {brand.name}")
544
+ print(f"Description: {brand.description}")
545
+ ```
546
+ """
547
+ if not brand_id or not brand_id.strip():
548
+ raise ValueError("brand_id cannot be empty")
549
+
550
+ url = f"{self.base_url}/brands/{brand_id}"
551
+
552
+ try:
553
+ async with aiohttp.ClientSession() as session:
554
+ async with session.get(
555
+ url, headers=self.headers, timeout=aiohttp.ClientTimeout(total=30)
556
+ ) as response:
557
+ response_data = await response.json()
558
+
559
+ if response.status != 200:
560
+ self._handle_error_response(response.status, response_data, url)
561
+
562
+ # Parse and validate response
563
+ return Brand(**response_data)
564
+
565
+ except aiohttp.ClientConnectionError as e:
566
+ raise Channel3ConnectionError(
567
+ f"Failed to connect to Channel3 API: {str(e)}"
568
+ )
569
+ except asyncio.TimeoutError as e:
570
+ raise Channel3ConnectionError(f"Request timed out: {str(e)}")
571
+ except aiohttp.ClientError as e:
572
+ raise Channel3Error(f"Request failed: {str(e)}")
573
+ except ValidationError as e:
574
+ raise Channel3Error(f"Invalid response format: {str(e)}")
channel3_sdk/models.py CHANGED
@@ -30,25 +30,21 @@ class Price(BaseModel):
30
30
  currency: str = Field(..., description="The currency code of the product.")
31
31
 
32
32
 
33
- class MerchantOffering(BaseModel):
34
- """A merchant offering a product."""
33
+ class Brand(BaseModel):
34
+ """A brand."""
35
35
 
36
- url: str = Field(
37
- default="https://buy.trychannel3.com", description="URL to purchase the product"
38
- )
39
- merchant_name: str = Field(..., description="Name of the merchant")
40
- price: Price = Field(..., description="Price information")
41
- availability: AvailabilityStatus = Field(
42
- ..., description="Product availability status"
43
- )
36
+ id: str = Field(..., description="Unique identifier for the brand")
37
+ name: str = Field(..., description="Name of the brand")
38
+ logo_url: Optional[str] = Field(None, description="Logo URL for the brand")
39
+ description: Optional[str] = Field(None, description="Description of the brand")
44
40
 
45
41
 
46
- class FamilyMember(BaseModel):
47
- """A family member product."""
42
+ class Variant(BaseModel):
43
+ """A product variant."""
48
44
 
49
- id: str = Field(..., description="Unique identifier for the family member")
50
- title: str = Field(..., description="Title of the family member product")
51
- image_url: str = Field(..., description="Image URL for the family member product")
45
+ product_id: str = Field(..., description="Unique identifier for the product")
46
+ title: str = Field(..., description="Title of the variant")
47
+ image_url: str = Field(..., description="Image URL for the variant")
52
48
 
53
49
 
54
50
  class Product(BaseModel):
@@ -56,38 +52,38 @@ class Product(BaseModel):
56
52
 
57
53
  id: str = Field(..., description="Unique identifier for the product")
58
54
  score: float = Field(..., description="Relevance score for the search query")
59
- brand_name: str = Field(..., description="Brand name of the product")
60
55
  title: str = Field(..., description="Product title")
61
- description: str = Field(..., description="Product description")
56
+ description: Optional[str] = Field(None, description="Product description")
57
+ brand_name: str = Field(..., description="Brand name of the product")
62
58
  image_url: str = Field(..., description="Main product image URL")
63
- offers: List[MerchantOffering] = Field(
64
- ..., description="List of merchant offerings"
59
+ price: Price = Field(..., description="Price information")
60
+ availability: AvailabilityStatus = Field(
61
+ ..., description="Product availability status"
65
62
  )
66
- family: List[FamilyMember] = Field(
67
- default_factory=list, description="Related family products"
63
+ variants: List[Variant] = Field(
64
+ default_factory=list, description="Product variants"
68
65
  )
69
66
 
70
67
 
71
68
  class ProductDetail(BaseModel):
72
69
  """Detailed information about a product."""
73
70
 
74
- brand_id: str = Field(..., description="Unique identifier for the brand")
75
- brand_name: str = Field(..., description="Brand name of the product")
76
71
  title: str = Field(..., description="Product title")
77
- description: str = Field(..., description="Product description")
78
- image_urls: List[str] = Field(..., description="List of product image URLs")
79
- merchant_offerings: List[MerchantOffering] = Field(
80
- ..., description="List of merchant offerings"
72
+ description: Optional[str] = Field(None, description="Product description")
73
+ brand_id: Optional[str] = Field(None, description="Unique identifier for the brand")
74
+ brand_name: Optional[str] = Field(None, description="Brand name of the product")
75
+ image_urls: Optional[List[str]] = Field(
76
+ None, description="List of product image URLs"
81
77
  )
82
- gender: Literal["na", "men", "women"] = Field(
83
- default="na", description="Target gender"
78
+ price: Price = Field(..., description="Price information")
79
+ availability: AvailabilityStatus = Field(
80
+ ..., description="Product availability status"
84
81
  )
85
- materials: Optional[List[str]] = Field(None, description="List of materials")
86
- key_features: List[str] = Field(
87
- default_factory=list, description="List of key product features"
82
+ key_features: Optional[List[str]] = Field(
83
+ None, description="List of key product features"
88
84
  )
89
- family_members: List[FamilyMember] = Field(
90
- default_factory=list, description="Related family products"
85
+ variants: List[Variant] = Field(
86
+ default_factory=list, description="Product variants"
91
87
  )
92
88
 
93
89
 
@@ -101,15 +97,17 @@ class SearchFilterPrice(BaseModel):
101
97
  class SearchFilters(BaseModel):
102
98
  """Search filters for product search."""
103
99
 
104
- brands: Optional[List[str]] = Field(None, description="List of brands to filter by")
100
+ brand_ids: Optional[List[str]] = Field(
101
+ None, description="List of brand IDs to filter by"
102
+ )
105
103
  gender: Optional[Literal["male", "female", "unisex"]] = Field(
106
104
  None, description="Gender to filter by"
107
105
  )
108
106
  price: Optional[SearchFilterPrice] = Field(
109
107
  None, description="Price range to filter by"
110
108
  )
111
- availability: Optional[AvailabilityStatus] = Field(
112
- None, description="Availability status to filter by"
109
+ availability: Optional[List[AvailabilityStatus]] = Field(
110
+ None, description="Availability statuses to filter by"
113
111
  )
114
112
 
115
113
 
@@ -121,9 +119,7 @@ class SearchRequest(BaseModel):
121
119
  base64_image: Optional[str] = Field(
122
120
  None, description="Base64-encoded image for visual search"
123
121
  )
124
- filters: SearchFilters = Field(
125
- default_factory=SearchFilters, description="Search filters"
126
- )
127
122
  limit: Optional[int] = Field(
128
123
  default=20, description="Maximum number of results to return"
129
124
  )
125
+ filters: Optional[SearchFilters] = Field(default=None, description="Search filters")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: channel3-sdk
3
- Version: 0.1.1
3
+ Version: 0.1.12
4
4
  Summary: The official Python SDK for Channel3 AI Shopping API
5
5
  Home-page: https://github.com/channel3/sdk-python
6
6
  License: MIT
@@ -50,14 +50,27 @@ products = client.search(query="blue denim jacket")
50
50
  for product in products:
51
51
  print(f"Product: {product.title}")
52
52
  print(f"Brand: {product.brand_name}")
53
- print(f"Price: ${product.offers[0].price.price}")
53
+ print(f"Price: {product.price.currency} {product.price.price}")
54
+ print(f"Availability: {product.availability}")
54
55
  print("---")
55
56
 
56
57
  # Get detailed product information
57
58
  product_detail = client.get_product("prod_123456")
58
59
  print(f"Detailed info for: {product_detail.title}")
59
- print(f"Materials: {product_detail.materials}")
60
- print(f"Key features: {product_detail.key_features}")
60
+ print(f"Brand: {product_detail.brand_name}")
61
+ if product_detail.key_features:
62
+ print(f"Key features: {product_detail.key_features}")
63
+
64
+ # Get all brands
65
+ brands = client.get_brands()
66
+ for brand in brands:
67
+ print(f"Brand: {brand.name}")
68
+ if brand.description:
69
+ print(f"Description: {brand.description}")
70
+
71
+ # Get specific brand details
72
+ brand = client.get_brand("brand_123")
73
+ print(f"Brand: {brand.name}")
61
74
  ```
62
75
 
63
76
  ### Asynchronous Client
@@ -76,11 +89,16 @@ async def main():
76
89
  for product in products:
77
90
  print(f"Product: {product.title}")
78
91
  print(f"Score: {product.score}")
92
+ print(f"Price: {product.price.currency} {product.price.price}")
79
93
 
80
94
  # Get detailed product information
81
95
  if products:
82
96
  product_detail = await client.get_product(products[0].id)
83
- print(f"Gender: {product_detail.gender}")
97
+ print(f"Availability: {product_detail.availability}")
98
+
99
+ # Get brands
100
+ brands = await client.get_brands()
101
+ print(f"Found {len(brands)} brands")
84
102
 
85
103
  # Run the async function
86
104
  asyncio.run(main())
@@ -114,14 +132,14 @@ products = client.search(
114
132
  ### Search with Filters
115
133
 
116
134
  ```python
117
- from channel3_sdk import SearchFilters
135
+ from channel3_sdk import SearchFilters, AvailabilityStatus
118
136
 
119
137
  # Create search filters
120
138
  filters = SearchFilters(
121
- colors=["blue", "navy"],
122
- materials=["cotton", "denim"],
123
- min_price=50.0,
124
- max_price=200.0
139
+ brand_ids=["brand_123", "brand_456"],
140
+ gender="male",
141
+ availability=[AvailabilityStatus.IN_STOCK],
142
+ price={"min_price": 50.0, "max_price": 200.0}
125
143
  )
126
144
 
127
145
  # Search with filters
@@ -132,6 +150,21 @@ products = client.search(
132
150
  )
133
151
  ```
134
152
 
153
+ ### Brand Management
154
+
155
+ ```python
156
+ # Get all brands with pagination
157
+ brands = client.get_brands(page=1, size=50)
158
+
159
+ # Search for specific brands
160
+ nike_brands = client.get_brands(query="nike")
161
+
162
+ # Get detailed brand information
163
+ brand_detail = client.get_brand("brand_123")
164
+ print(f"Brand: {brand_detail.name}")
165
+ print(f"Logo: {brand_detail.logo_url}")
166
+ ```
167
+
135
168
  ## API Reference
136
169
 
137
170
  ### Client Classes
@@ -142,6 +175,8 @@ Synchronous client for the Channel3 API.
142
175
  **Methods:**
143
176
  - `search(query=None, image_url=None, base64_image=None, filters=None, limit=20)` → `List[Product]`
144
177
  - `get_product(product_id)` → `ProductDetail`
178
+ - `get_brands(query=None, page=1, size=100)` → `List[Brand]`
179
+ - `get_brand(brand_id)` → `Brand`
145
180
 
146
181
  #### `AsyncChannel3Client`
147
182
  Asynchronous client for the Channel3 API.
@@ -149,48 +184,62 @@ Asynchronous client for the Channel3 API.
149
184
  **Methods:**
150
185
  - `async search(query=None, image_url=None, base64_image=None, filters=None, limit=20)` → `List[Product]`
151
186
  - `async get_product(product_id)` → `ProductDetail`
187
+ - `async get_brands(query=None, page=1, size=100)` → `List[Brand]`
188
+ - `async get_brand(brand_id)` → `Brand`
152
189
 
153
190
  ### Models
154
191
 
155
192
  #### `Product`
156
193
  - `id: str` - Unique product identifier
157
194
  - `score: float` - Search relevance score
158
- - `brand_name: str` - Brand name
159
195
  - `title: str` - Product title
160
- - `description: str` - Product description
196
+ - `description: Optional[str]` - Product description
197
+ - `brand_name: str` - Brand name
161
198
  - `image_url: str` - Main product image URL
162
- - `offers: List[MerchantOffering]` - Available purchase options
163
- - `family: List[FamilyMember]` - Related products
199
+ - `price: Price` - Price information
200
+ - `availability: AvailabilityStatus` - Availability status
201
+ - `variants: List[Variant]` - Product variants
164
202
 
165
203
  #### `ProductDetail`
166
- - `brand_id: str` - Brand identifier
167
- - `brand_name: str` - Brand name
168
204
  - `title: str` - Product title
169
- - `description: str` - Product description
170
- - `image_urls: List[str]` - Product image URLs
171
- - `merchant_offerings: List[MerchantOffering]` - Purchase options
172
- - `gender: Literal["na", "men", "women"]` - Target gender
173
- - `materials: Optional[List[str]]` - Product materials
174
- - `key_features: List[str]` - Key product features
175
- - `family_members: List[FamilyMember]` - Related products
205
+ - `description: Optional[str]` - Product description
206
+ - `brand_id: Optional[str]` - Brand identifier
207
+ - `brand_name: Optional[str]` - Brand name
208
+ - `image_urls: Optional[List[str]]` - Product image URLs
209
+ - `price: Price` - Price information
210
+ - `availability: AvailabilityStatus` - Availability status
211
+ - `key_features: Optional[List[str]]` - Key product features
212
+ - `variants: List[Variant]` - Product variants
213
+
214
+ #### `Brand`
215
+ - `id: str` - Unique brand identifier
216
+ - `name: str` - Brand name
217
+ - `logo_url: Optional[str]` - Brand logo URL
218
+ - `description: Optional[str]` - Brand description
219
+
220
+ #### `Variant`
221
+ - `product_id: str` - Associated product identifier
222
+ - `title: str` - Variant title
223
+ - `image_url: str` - Variant image URL
176
224
 
177
225
  #### `SearchFilters`
178
- - `colors: Optional[List[str]]` - Color filters
179
- - `materials: Optional[List[str]]` - Material filters
226
+ - `brand_ids: Optional[List[str]]` - Brand ID filters
227
+ - `gender: Optional[Literal["male", "female", "unisex"]]` - Gender filter
228
+ - `price: Optional[SearchFilterPrice]` - Price range filter
229
+ - `availability: Optional[List[AvailabilityStatus]]` - Availability filters
230
+
231
+ #### `SearchFilterPrice`
180
232
  - `min_price: Optional[float]` - Minimum price
181
233
  - `max_price: Optional[float]` - Maximum price
182
234
 
183
- #### `MerchantOffering`
184
- - `url: str` - Purchase URL
185
- - `merchant_name: str` - Merchant name
186
- - `price: Price` - Price information
187
- - `availability: AvailabilityStatus` - Availability status
188
-
189
235
  #### `Price`
190
236
  - `price: float` - Current price
191
237
  - `compare_at_price: Optional[float]` - Original price (if discounted)
192
238
  - `currency: str` - Currency code
193
239
 
240
+ #### `AvailabilityStatus`
241
+ Enum with values: `IN_STOCK`, `OUT_OF_STOCK`, `PRE_ORDER`, `LIMITED_AVAILABILITY`, `BACK_ORDER`, `DISCONTINUED`, `SOLD_OUT`, `UNKNOWN`
242
+
194
243
  ## Error Handling
195
244
 
196
245
  The SDK provides specific exception types for different error conditions:
@@ -0,0 +1,7 @@
1
+ channel3_sdk/__init__.py,sha256=vMrsZwY59OoYmoPwEnZ0kuAuWFkOIERUaoy0lWpGIlc,976
2
+ channel3_sdk/client.py,sha256=8klt__VDUerEO6qq8-RA3w8CSImE6tfPf1v8m25_aS4,20843
3
+ channel3_sdk/exceptions.py,sha256=5HJgrhir4-_b4XKyWAB9qp-CjVZeigXSkyM9fbcB1IA,1044
4
+ channel3_sdk/models.py,sha256=PdFD-sESRhlZSsvVIHHlhwn-Zi5QbGcUiHo0NnP_Gqs,4520
5
+ channel3_sdk-0.1.12.dist-info/METADATA,sha256=fflKnYaOYNhHohAMm7_MvdDgxBxOHZfXtJCYsbwj4FA,7800
6
+ channel3_sdk-0.1.12.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
+ channel3_sdk-0.1.12.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- channel3_sdk/__init__.py,sha256=aoe0MhblA5pEOd7iAggJ94u1Os8-xCBs6k0UWhfOiiE,960
2
- channel3_sdk/client.py,sha256=JuJFtXdWsezwOQk3nVUnxhdtQp300UEORsQZdCZ77V8,12525
3
- channel3_sdk/exceptions.py,sha256=5HJgrhir4-_b4XKyWAB9qp-CjVZeigXSkyM9fbcB1IA,1044
4
- channel3_sdk/models.py,sha256=kKrKJQz0LXsBhziaxtl43gXa-J2uOdw_2HP97gB2cp8,4679
5
- channel3_sdk-0.1.1.dist-info/METADATA,sha256=CTaXUKdaLNy8dMFv7IJFlUqBYhTwnqQEO2e2HsKFGzc,6137
6
- channel3_sdk-0.1.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
- channel3_sdk-0.1.1.dist-info/RECORD,,