storerouter 0.1.0__tar.gz
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.
- storerouter-0.1.0/PKG-INFO +391 -0
- storerouter-0.1.0/README.md +362 -0
- storerouter-0.1.0/pyproject.toml +92 -0
- storerouter-0.1.0/pyproject.toml.orig +85 -0
- storerouter-0.1.0/src/storerouter/__init__.py +90 -0
- storerouter-0.1.0/src/storerouter/_client.py +348 -0
- storerouter-0.1.0/src/storerouter/_retry.py +92 -0
- storerouter-0.1.0/src/storerouter/models.py +25 -0
- storerouter-0.1.0/src/storerouter/py.typed +0 -0
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: storerouter
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for StoreRouter: look up any product URL as structured JSON, search products across stores, and discover brands and stores
|
|
5
|
+
Keywords: storerouter,ecommerce,product-data,product-search,product-lookup,web-scraping,structured-data,shopping,ai-agents,sdk
|
|
6
|
+
Author: StoreRouter (Octogen AI)
|
|
7
|
+
License-Expression: Apache-2.0
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
16
|
+
Classifier: Topic :: Office/Business
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: httpx>=0.28.1
|
|
20
|
+
Requires-Dist: octogen-ai-sdk>=0.17.0,<1.0.0
|
|
21
|
+
Requires-Dist: pydantic>=2.0
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Project-URL: Homepage, https://storerouter.ai
|
|
24
|
+
Project-URL: Documentation, https://storerouter.ai/docs
|
|
25
|
+
Project-URL: Source, https://github.com/octogen-ai/octogen-dev/tree/main/sdks/storerouter-python
|
|
26
|
+
Project-URL: Issues, https://github.com/octogen-ai/octogen-dev/issues
|
|
27
|
+
Project-URL: Changelog, https://github.com/octogen-ai/octogen-dev/blob/main/sdks/storerouter-python/CHANGELOG.md
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# StoreRouter Python SDK
|
|
31
|
+
|
|
32
|
+
[](https://pypi.org/project/storerouter/)
|
|
33
|
+
[](https://pypi.org/project/storerouter/)
|
|
34
|
+
[](https://github.com/octogen-ai/octogen-dev/blob/main/LICENSE)
|
|
35
|
+
|
|
36
|
+
`storerouter` is the official Python SDK for [StoreRouter](https://storerouter.ai),
|
|
37
|
+
an API that returns **structured e-commerce product data**. Use it to:
|
|
38
|
+
|
|
39
|
+
- turn a product page URL into normalized JSON (title, brand, price, currency,
|
|
40
|
+
stock, variants, images, identifiers, taxonomy category and attributes);
|
|
41
|
+
- search products across thousands of stores, or only the stores you name;
|
|
42
|
+
- discover stores and brands.
|
|
43
|
+
|
|
44
|
+
Every result uses **one product schema**, whatever store it came from, and
|
|
45
|
+
every response is a typed Pydantic model. The package has sync and async
|
|
46
|
+
clients, and it retries 429 and 5xx responses for you.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install storerouter
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quickstart
|
|
53
|
+
|
|
54
|
+
Get an API key at [dev.storerouter.ai](https://dev.storerouter.ai) and export it:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
export STOREROUTER_API_KEY="sk_..."
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from storerouter import StoreRouter
|
|
62
|
+
|
|
63
|
+
client = StoreRouter() # reads STOREROUTER_API_KEY
|
|
64
|
+
|
|
65
|
+
result = client.lookup_product(
|
|
66
|
+
"https://www.allbirds.com/products/mens-runner-nz-jersey-light-grey-syrah"
|
|
67
|
+
)
|
|
68
|
+
product = result.product
|
|
69
|
+
print(product.title, product.current_price, product.currency, product.in_stock)
|
|
70
|
+
# Men's Runner NZ Jersey - Light Grey/Syrah (Blizzard Sole) 110.0 USD True
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Look up a product URL
|
|
74
|
+
|
|
75
|
+
`lookup_product` takes the URL of any product page. It returns the indexed
|
|
76
|
+
product when StoreRouter already has it, and otherwise extracts the page on
|
|
77
|
+
demand. `result.source` says which: `"indexed"` or `"on_demand"`.
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
result = client.lookup_product(
|
|
81
|
+
"https://www.allbirds.com/products/mens-runner-nz-jersey-light-grey-syrah"
|
|
82
|
+
)
|
|
83
|
+
print(result.product.model_dump_json(by_alias=True, exclude_none=True, indent=2))
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
This is real output, shortened. It shows one of 19 variants and some of the
|
|
87
|
+
enrichment attributes. It leaves out the description, the long brand
|
|
88
|
+
description, the image list, the store's own attributes and the request ID on
|
|
89
|
+
image URLs.
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"uuid": "2b7a52cc-93e4-545a-999c-ed6f41f54ea6",
|
|
94
|
+
"catalogKey": "allbirds",
|
|
95
|
+
"productUrl": "https://www.allbirds.com/products/mens-runner-nz-jersey-light-grey-syrah",
|
|
96
|
+
"title": "Men's Runner NZ Jersey - Light Grey/Syrah (Blizzard Sole)",
|
|
97
|
+
"brand": { "name": "Allbirds", "slug": "allbirds", "url": "www.allbirds.com" },
|
|
98
|
+
"currentPrice": 110.0,
|
|
99
|
+
"originalPrice": 110.0,
|
|
100
|
+
"currency": "USD",
|
|
101
|
+
"inStock": true,
|
|
102
|
+
"availability": "InStock",
|
|
103
|
+
"primaryImage": {
|
|
104
|
+
"url": "https://cdn.shopify.com/s/files/1/1104/4168/files/A12548_26Q1_Runner-NZ-Jersey-Light-Grey-Syrah-Bizzard-Sole_PDP_LEFT.png?v=1774551568",
|
|
105
|
+
"cdnUrl": "https://cdn.storerouter.ai/91b22b320476b49b1d658a81b4f2aad6/6afbe5a521bcb04aa95fbb111487a33d.webp",
|
|
106
|
+
"width": 4000,
|
|
107
|
+
"height": 4000,
|
|
108
|
+
"mimeType": "image/webp"
|
|
109
|
+
},
|
|
110
|
+
"sizes": [
|
|
111
|
+
"8",
|
|
112
|
+
"8.5",
|
|
113
|
+
"9",
|
|
114
|
+
"9.5",
|
|
115
|
+
"10",
|
|
116
|
+
"10.5",
|
|
117
|
+
"11",
|
|
118
|
+
"11.5",
|
|
119
|
+
"12",
|
|
120
|
+
"12.5",
|
|
121
|
+
"13",
|
|
122
|
+
"13.5",
|
|
123
|
+
"14"
|
|
124
|
+
],
|
|
125
|
+
"colors": [{ "label": "Light Grey/Syrah (Blizzard Sole)" }],
|
|
126
|
+
"categories": [{ "name": "Shoes" }],
|
|
127
|
+
"variants": [
|
|
128
|
+
{
|
|
129
|
+
"sku": "mens-runner-nz-jersey-light-grey-syrah",
|
|
130
|
+
"productUrl": "https://www.allbirds.com/products/mens-runner-nz-jersey-light-grey-syrah",
|
|
131
|
+
"color": { "label": "Light Grey/Syrah (Blizzard Sole)" },
|
|
132
|
+
"inStock": true,
|
|
133
|
+
"availability": "InStock",
|
|
134
|
+
"currentPrice": 110.0,
|
|
135
|
+
"currency": "USD"
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"identifiers": { "productId": "7258388856912", "productGroupId": "7258388856912" },
|
|
139
|
+
"details": { "materials": ["cotton"], "fit": [], "patterns": [] },
|
|
140
|
+
"audience": { "genders": ["male"], "ageGroups": ["adult"] },
|
|
141
|
+
"enrichment": {
|
|
142
|
+
"type": "sneakers",
|
|
143
|
+
"category_path": ["Apparel & Accessories", "Shoes", "Sneakers"],
|
|
144
|
+
"color_family": ["Gray", "Red", "White"],
|
|
145
|
+
"gender": "male",
|
|
146
|
+
"age_groups": ["adult"],
|
|
147
|
+
"attributes": {
|
|
148
|
+
"Activity Type": ["Running"],
|
|
149
|
+
"Closure type": ["Lace-Up"],
|
|
150
|
+
"Footwear material": ["Cotton"],
|
|
151
|
+
"Sneaker style": ["Athletic"],
|
|
152
|
+
"Shoe Type (Silhouette/Style)": ["Low-Top"]
|
|
153
|
+
},
|
|
154
|
+
"summary": "Men's light grey jersey textile sneakers featuring contrasting red laces and a clean white sole."
|
|
155
|
+
},
|
|
156
|
+
"languageCode": "en-US",
|
|
157
|
+
"updatedAt": "2026-11-06T10:34:25.665193Z"
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Want Markdown for an LLM prompt instead of JSON? Call
|
|
162
|
+
`client.lookup_product_markdown(url)`.
|
|
163
|
+
|
|
164
|
+
### Look up many URLs at once
|
|
165
|
+
|
|
166
|
+
`lookup_products` runs lookups concurrently (8 at a time by default) and
|
|
167
|
+
returns one `LookupResult` per URL, in the same order. A URL that fails does
|
|
168
|
+
not stop the batch.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
results = client.lookup_products([
|
|
172
|
+
"https://www.allbirds.com/products/mens-runner-nz-jersey-light-grey-syrah",
|
|
173
|
+
"https://www.jcrew.com/p/mens/categories/clothing/shirts/linen/short-sleeve-camp-collar-shirt-in-irish-linen/BG997",
|
|
174
|
+
"https://www.example.com/not-a-product",
|
|
175
|
+
])
|
|
176
|
+
for r in results:
|
|
177
|
+
if r.ok:
|
|
178
|
+
print("ok ", r.product.title, r.product.current_price)
|
|
179
|
+
else:
|
|
180
|
+
print("fail", r.url, type(r.error).__name__, r.error)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
ok Men's Runner NZ Jersey - Light Grey/Syrah (Blizzard Sole) 110.0
|
|
185
|
+
ok Short-sleeve camp-collar shirt in Irish linen 87.99
|
|
186
|
+
fail https://www.example.com/not-a-product OctogenNotFoundError product_not_found
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Search products
|
|
190
|
+
|
|
191
|
+
`search_products` takes a natural-language query. By default StoreRouter
|
|
192
|
+
understands it: it rewrites the query for retrieval and turns implied
|
|
193
|
+
constraints into filters. You can narrow the search with:
|
|
194
|
+
|
|
195
|
+
- `stores`: up to 20 store domains;
|
|
196
|
+
- `facets`: filters such as `color_family`, `gender`, `brand_name`,
|
|
197
|
+
`category_path.depth_N` and taxonomy attributes;
|
|
198
|
+
- `price_min` and `price_max`.
|
|
199
|
+
|
|
200
|
+
With `relax=True`, a query that finds nothing is retried with its filters
|
|
201
|
+
dropped in stages. Only the facets you mark `relaxable=True` can be dropped.
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from storerouter import SearchFacet
|
|
205
|
+
|
|
206
|
+
page = client.search_products(
|
|
207
|
+
q="linen shirt",
|
|
208
|
+
stores=["jcrew.com"],
|
|
209
|
+
facets=[SearchFacet(name="color_family", values=["Blue"], relaxable=True)],
|
|
210
|
+
relax=True,
|
|
211
|
+
limit=3,
|
|
212
|
+
)
|
|
213
|
+
for item in page.items:
|
|
214
|
+
print(f"{item.title} | {item.current_price} {item.currency} | {item.product_url}")
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
Short-sleeve camp-collar shirt in Irish linen | 87.99 USD | https://www.jcrew.com/p/mens/categories/clothing/shirts/linen/short-sleeve-camp-collar-shirt-in-irish-linen/BG997
|
|
219
|
+
Gamine button-up shirt in linen | 87.99 USD | https://www.jcrew.com/p/womens/categories/clothing/matching-sets/gamine-button-up-shirt-in-linen/CV033
|
|
220
|
+
Washed linen shirt with point collar | 104.99 USD | https://www.jcrew.com/p/mens/categories/clothing/shirts/linen/washed-linen-shirt-with-point-collar/CH601
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`page.effective_query` shows the search that actually ran: the understood
|
|
224
|
+
filters, and which facets `relax` dropped. To get the next page, pass
|
|
225
|
+
`cursor=page.next_cursor`. Each item is a `ProductListItem`, a lighter
|
|
226
|
+
version of `Product`. To get the full record, call `lookup_product` with the
|
|
227
|
+
item's URL, or `retrieve_products` with the item UUIDs.
|
|
228
|
+
|
|
229
|
+
Related calls:
|
|
230
|
+
|
|
231
|
+
- `count_product_facets`: facet value counts for a query;
|
|
232
|
+
- `more_like_this_products`: products similar to the ones you pass;
|
|
233
|
+
- `list_taxonomy_categories` and `list_taxonomy_attributes`: the category tree
|
|
234
|
+
and attribute names that facets accept.
|
|
235
|
+
|
|
236
|
+
## Stores and brands
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
store = client.get_store("allbirds.com") # is this store covered, and how well?
|
|
240
|
+
for catalog in store.catalogs:
|
|
241
|
+
print(catalog.catalog_display_name, catalog.product_count)
|
|
242
|
+
|
|
243
|
+
stores = client.search_stores("sustainable sneakers", limit=3)
|
|
244
|
+
print([s.store.primary_domain for s in stores.results])
|
|
245
|
+
# ['seavees.com', 'stellamccartney.com', '8000kicks.com']
|
|
246
|
+
|
|
247
|
+
brands = client.search_brands("minimalist sneakers", limit=3)
|
|
248
|
+
print([(b.brand_name, b.domain) for b in brands.results])
|
|
249
|
+
# [('Little Love Bug Co.', 'littlelovebugcompany.com'), ('ALIVEFORM', 'aliveform.co'), ('Camper', 'camper.com')]
|
|
250
|
+
|
|
251
|
+
brand = client.get_brand_details("allbirds")
|
|
252
|
+
print(brand.founded_year, brand.origin_country, brand.price_tier)
|
|
253
|
+
# 2016 New Zealand PREMIUM
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
More brand calls: `search_brand_prefix` (autocomplete), `search_similar_brands`,
|
|
257
|
+
`get_brand_directory`, `get_brand_coverage`, `browse_brand_products` and
|
|
258
|
+
`get_brand_top_categories`. For stores there is also `search_similar_stores`.
|
|
259
|
+
|
|
260
|
+
## Async
|
|
261
|
+
|
|
262
|
+
`AsyncStoreRouter` has the same constructor and the same methods as
|
|
263
|
+
`StoreRouter`, as coroutines:
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
import asyncio
|
|
267
|
+
from storerouter import AsyncStoreRouter
|
|
268
|
+
|
|
269
|
+
async def main() -> None:
|
|
270
|
+
async with AsyncStoreRouter() as client:
|
|
271
|
+
page = await client.search_products(q="wool sweater", limit=2)
|
|
272
|
+
print([item.title for item in page.items])
|
|
273
|
+
|
|
274
|
+
asyncio.run(main())
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
`StoreRouter` runs the async client on a private event-loop thread. It
|
|
278
|
+
therefore works inside Jupyter and other code that already runs an event
|
|
279
|
+
loop. Close it with `client.close()`, or use it in a `with` block.
|
|
280
|
+
|
|
281
|
+
## The normalized product schema
|
|
282
|
+
|
|
283
|
+
Every lookup returns a `Product` (`storerouter.models.Product`). Every search
|
|
284
|
+
result is a `ProductListItem`, which is a subset of `Product`. Python
|
|
285
|
+
attributes use snake_case. The JSON wire format uses camelCase:
|
|
286
|
+
`model_dump(by_alias=True)`.
|
|
287
|
+
|
|
288
|
+
| Field | What it holds |
|
|
289
|
+
| ------------------------------------ | ---------------------------------------------------------------------------------------------- |
|
|
290
|
+
| `uuid`, `catalog_key`, `product_url` | StoreRouter's stable ID, the store's catalog, and the canonical product URL |
|
|
291
|
+
| `title`, `description` | As the store states them |
|
|
292
|
+
| `brand` | `name`, `slug`, `url`, `description` |
|
|
293
|
+
| `current_price`, `original_price` | Sale price and list price, as numbers |
|
|
294
|
+
| `currency` | ISO 4217 code, for example `USD` |
|
|
295
|
+
| `in_stock`, `availability` | Stock rolled up across variants, and the schema.org availability term |
|
|
296
|
+
| `variants` | Per-variant `sku`, `color`, `size`, `in_stock`, `current_price`, `original_price`, `image_url` |
|
|
297
|
+
| `sizes`, `colors` | Sizes and color labels (with swatches and hex codes when the store has them) |
|
|
298
|
+
| `primary_image`, `images` | Store image URL plus a StoreRouter CDN copy (`cdn_url`), with dimensions |
|
|
299
|
+
| `identifiers` | `product_id`, `gtin`, `product_group_id` |
|
|
300
|
+
| `categories`, `breadcrumbs` | The store's own categories and breadcrumb trail |
|
|
301
|
+
| `details` | `materials`, `fit`, `dimensions`, `patterns` |
|
|
302
|
+
| `audience` | `genders`, `age_groups` |
|
|
303
|
+
| `rating`, `reviews` | Aggregate rating and individual reviews |
|
|
304
|
+
| `promotions`, `videos`, `tags` | Promotions with codes, product videos, and store tags |
|
|
305
|
+
| `additional_attributes` | Name/value pairs as the store states them |
|
|
306
|
+
| `enrichment` | Added by StoreRouter (see below) |
|
|
307
|
+
| `item_condition`, `language_code` | schema.org item condition, and the language of the text |
|
|
308
|
+
| `updated_at` | When StoreRouter last refreshed the product |
|
|
309
|
+
|
|
310
|
+
StoreRouter adds `enrichment` itself. It holds:
|
|
311
|
+
|
|
312
|
+
- the product `type`;
|
|
313
|
+
- a taxonomy `category_path`, root first;
|
|
314
|
+
- `color_family`, `gender`, `age_groups` and `styles`;
|
|
315
|
+
- category-specific `attributes`: fit and fabric for apparel, skin type for
|
|
316
|
+
skincare, notes for fragrance, upholstery for furniture;
|
|
317
|
+
- a `canonical_brand` profile;
|
|
318
|
+
- a one-line `summary`.
|
|
319
|
+
|
|
320
|
+
The full machine-readable schema is the
|
|
321
|
+
[OpenAPI document](https://cdn.storerouter.ai/openapi/platform/v1/openapi.json).
|
|
322
|
+
|
|
323
|
+
## Errors and retries
|
|
324
|
+
|
|
325
|
+
The client retries 429, 500, 502, 503 and 504 responses, and connections that
|
|
326
|
+
fail to open. It waits for `Retry-After` when the server sends one, and uses
|
|
327
|
+
exponential backoff otherwise. Read timeouts are not retried. Set the number
|
|
328
|
+
of retries with `StoreRouter(max_retries=...)` (the default is 2, and 0
|
|
329
|
+
disables retries).
|
|
330
|
+
|
|
331
|
+
When a call fails, it raises a typed error. Each one is an alias of the
|
|
332
|
+
matching `octogen_ai_sdk` error:
|
|
333
|
+
|
|
334
|
+
| Error | When |
|
|
335
|
+
| ------------------------- | ---------------------------------------------------- |
|
|
336
|
+
| `MissingAPIKeyError` | No key passed, and none in the environment |
|
|
337
|
+
| `AuthenticationError` | 401: the key is invalid |
|
|
338
|
+
| `InsufficientCreditError` | 402: the organization is out of credit |
|
|
339
|
+
| `PermissionDeniedError` | 403: the key cannot use this endpoint or catalog |
|
|
340
|
+
| `NotFoundError` | 404: product not found, or store not covered |
|
|
341
|
+
| `ValidationError` | 422: invalid request |
|
|
342
|
+
| `RateLimitError` | 429 after retries; `error.retry_after` is in seconds |
|
|
343
|
+
| `InternalServerError` | 5xx after retries |
|
|
344
|
+
| `APITimeoutError` | The request timed out |
|
|
345
|
+
| `APIConnectionError` | Network failure |
|
|
346
|
+
|
|
347
|
+
`APIError` is the base class of every HTTP error, and `StoreRouterError` is
|
|
348
|
+
the base class of them all. HTTP errors carry `status_code`, `detail` and
|
|
349
|
+
`request_id`.
|
|
350
|
+
|
|
351
|
+
## Configuration
|
|
352
|
+
|
|
353
|
+
| Setting | Argument | Environment variable | Default |
|
|
354
|
+
| -------- | --------------------------------------- | ------------------------------------------------------- | ------------------------------- |
|
|
355
|
+
| API key | `api_key=` | `STOREROUTER_API_KEY` (then `OCTOGEN_PLATFORM_API_KEY`) | required |
|
|
356
|
+
| Base URL | `base_url=` | `STOREROUTER_BASE_URL` | `https://api.storerouter.ai/v1` |
|
|
357
|
+
| Timeout | `timeout=` (seconds or `httpx.Timeout`) | | 60 s |
|
|
358
|
+
| Retries | `max_retries=` | | 2 |
|
|
359
|
+
|
|
360
|
+
Every method also accepts a per-call `timeout=`. Requests use
|
|
361
|
+
`Authorization: Bearer <key>`. Billing is per successful request, and every
|
|
362
|
+
organization gets free credit each month: see
|
|
363
|
+
[pricing](https://storerouter.ai/docs/guides/pricing-and-billing).
|
|
364
|
+
|
|
365
|
+
## Other ways to use StoreRouter
|
|
366
|
+
|
|
367
|
+
- **MCP server for AI agents**: `https://mcp.dev.storerouter.ai/mcp`
|
|
368
|
+
(Streamable HTTP with OAuth). It gives Claude, ChatGPT, Cursor and other MCP
|
|
369
|
+
clients product search, product lookup, and store and brand tools. See the
|
|
370
|
+
[setup guides](https://storerouter.ai/docs/mcp/overview).
|
|
371
|
+
- **LangChain**: [`langchain-storerouter`](https://pypi.org/project/langchain-storerouter/)
|
|
372
|
+
- **TypeScript**: [`@storerouter/sdk`](https://www.npmjs.com/package/@storerouter/sdk)
|
|
373
|
+
- **CLI**: [`@storerouter/cli`](https://www.npmjs.com/package/@storerouter/cli)
|
|
374
|
+
- **REST**: the [API reference](https://storerouter.ai/docs/api-reference)
|
|
375
|
+
and the [OpenAPI document](https://cdn.storerouter.ai/openapi/platform/v1/openapi.json)
|
|
376
|
+
|
|
377
|
+
`storerouter` is built on [`octogen-ai-sdk`](https://pypi.org/project/octogen-ai-sdk/),
|
|
378
|
+
the lower-level async SDK for the same API. It adds the sync client, retries,
|
|
379
|
+
batch lookup and the `STOREROUTER_*` settings. Every `octogen_ai_sdk` model is
|
|
380
|
+
available from `storerouter.models`.
|
|
381
|
+
|
|
382
|
+
## Documentation
|
|
383
|
+
|
|
384
|
+
- [StoreRouter docs](https://storerouter.ai/docs)
|
|
385
|
+
- [API reference](https://storerouter.ai/docs/api-reference)
|
|
386
|
+
- [MCP server](https://storerouter.ai/docs/mcp/overview)
|
|
387
|
+
- [Source and issues](https://github.com/octogen-ai/octogen-dev/tree/main/sdks/storerouter-python)
|
|
388
|
+
|
|
389
|
+
## License
|
|
390
|
+
|
|
391
|
+
Apache-2.0
|