ordercloud-python 2026.4.1__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.
Files changed (114) hide show
  1. ordercloud/__init__.py +37 -0
  2. ordercloud/auth.py +136 -0
  3. ordercloud/client.py +211 -0
  4. ordercloud/config.py +42 -0
  5. ordercloud/errors.py +47 -0
  6. ordercloud/http.py +218 -0
  7. ordercloud/middleware.py +66 -0
  8. ordercloud/models/__init__.py +271 -0
  9. ordercloud/models/address.py +47 -0
  10. ordercloud/models/api_client.py +116 -0
  11. ordercloud/models/approval.py +73 -0
  12. ordercloud/models/assignments.py +402 -0
  13. ordercloud/models/auth_models.py +114 -0
  14. ordercloud/models/bundle.py +31 -0
  15. ordercloud/models/buyer.py +271 -0
  16. ordercloud/models/catalog.py +33 -0
  17. ordercloud/models/category.py +35 -0
  18. ordercloud/models/cost_center.py +27 -0
  19. ordercloud/models/credit_card.py +35 -0
  20. ordercloud/models/delivery.py +277 -0
  21. ordercloud/models/discount.py +63 -0
  22. ordercloud/models/integration.py +76 -0
  23. ordercloud/models/inventory_record.py +53 -0
  24. ordercloud/models/line_item.py +95 -0
  25. ordercloud/models/line_item_types.py +89 -0
  26. ordercloud/models/message_sender.py +80 -0
  27. ordercloud/models/misc.py +280 -0
  28. ordercloud/models/open_id_connect.py +47 -0
  29. ordercloud/models/order.py +477 -0
  30. ordercloud/models/order_return.py +92 -0
  31. ordercloud/models/payment.py +77 -0
  32. ordercloud/models/price_schedule.py +76 -0
  33. ordercloud/models/product.py +227 -0
  34. ordercloud/models/product_collection.py +186 -0
  35. ordercloud/models/promotion.py +297 -0
  36. ordercloud/models/security.py +89 -0
  37. ordercloud/models/shared.py +131 -0
  38. ordercloud/models/shipment.py +150 -0
  39. ordercloud/models/spec.py +67 -0
  40. ordercloud/models/spending_account.py +33 -0
  41. ordercloud/models/subscription.py +125 -0
  42. ordercloud/models/supplier.py +43 -0
  43. ordercloud/models/sync.py +172 -0
  44. ordercloud/models/user.py +207 -0
  45. ordercloud/models/user_group.py +27 -0
  46. ordercloud/models/webhook.py +58 -0
  47. ordercloud/py.typed +0 -0
  48. ordercloud/resources/__init__.py +65 -0
  49. ordercloud/resources/addresses.py +228 -0
  50. ordercloud/resources/admin_addresses.py +128 -0
  51. ordercloud/resources/admin_user_groups.py +185 -0
  52. ordercloud/resources/admin_users.py +150 -0
  53. ordercloud/resources/api_clients.py +308 -0
  54. ordercloud/resources/approval_rules.py +144 -0
  55. ordercloud/resources/base.py +145 -0
  56. ordercloud/resources/bundle_line_items.py +59 -0
  57. ordercloud/resources/bundle_subscription_items.py +54 -0
  58. ordercloud/resources/bundles.py +278 -0
  59. ordercloud/resources/buyer_groups.py +128 -0
  60. ordercloud/resources/buyers.py +164 -0
  61. ordercloud/resources/cart.py +613 -0
  62. ordercloud/resources/catalogs.py +311 -0
  63. ordercloud/resources/categories.py +392 -0
  64. ordercloud/resources/cost_centers.py +222 -0
  65. ordercloud/resources/credit_cards.py +227 -0
  66. ordercloud/resources/delivery_configurations.py +132 -0
  67. ordercloud/resources/discounts.py +201 -0
  68. ordercloud/resources/entity_syncs.py +534 -0
  69. ordercloud/resources/error_configs.py +71 -0
  70. ordercloud/resources/forgotten_credentials.py +74 -0
  71. ordercloud/resources/group_orders.py +28 -0
  72. ordercloud/resources/impersonation_configs.py +132 -0
  73. ordercloud/resources/incrementors.py +128 -0
  74. ordercloud/resources/integration_events.py +203 -0
  75. ordercloud/resources/inventory_integrations.py +65 -0
  76. ordercloud/resources/inventory_records.py +484 -0
  77. ordercloud/resources/line_items.py +262 -0
  78. ordercloud/resources/locales.py +203 -0
  79. ordercloud/resources/me.py +1882 -0
  80. ordercloud/resources/message_senders.py +261 -0
  81. ordercloud/resources/open_id_connects.py +128 -0
  82. ordercloud/resources/order_returns.py +306 -0
  83. ordercloud/resources/order_syncs.py +65 -0
  84. ordercloud/resources/orders.py +689 -0
  85. ordercloud/resources/payments.py +176 -0
  86. ordercloud/resources/price_schedules.py +164 -0
  87. ordercloud/resources/product_collections.py +116 -0
  88. ordercloud/resources/product_facets.py +128 -0
  89. ordercloud/resources/product_syncs.py +76 -0
  90. ordercloud/resources/products.py +454 -0
  91. ordercloud/resources/promotion_integrations.py +65 -0
  92. ordercloud/resources/promotions.py +203 -0
  93. ordercloud/resources/security_profiles.py +222 -0
  94. ordercloud/resources/seller_approval_rules.py +128 -0
  95. ordercloud/resources/shipments.py +256 -0
  96. ordercloud/resources/specs.py +313 -0
  97. ordercloud/resources/spending_accounts.py +227 -0
  98. ordercloud/resources/subscription_integrations.py +65 -0
  99. ordercloud/resources/subscription_items.py +146 -0
  100. ordercloud/resources/subscriptions.py +128 -0
  101. ordercloud/resources/supplier_addresses.py +144 -0
  102. ordercloud/resources/supplier_user_groups.py +210 -0
  103. ordercloud/resources/supplier_users.py +170 -0
  104. ordercloud/resources/suppliers.py +190 -0
  105. ordercloud/resources/tracking_events.py +130 -0
  106. ordercloud/resources/user_groups.py +210 -0
  107. ordercloud/resources/users.py +254 -0
  108. ordercloud/resources/webhooks.py +128 -0
  109. ordercloud/resources/xp_indices.py +77 -0
  110. ordercloud/sync_client.py +170 -0
  111. ordercloud_python-2026.4.1.dist-info/METADATA +552 -0
  112. ordercloud_python-2026.4.1.dist-info/RECORD +114 -0
  113. ordercloud_python-2026.4.1.dist-info/WHEEL +4 -0
  114. ordercloud_python-2026.4.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,552 @@
1
+ Metadata-Version: 2.4
2
+ Name: ordercloud-python
3
+ Version: 2026.4.1
4
+ Summary: Idiomatic Python SDK for Sitecore OrderCloud
5
+ Project-URL: Homepage, https://github.com/markcassidyconsulting/ordercloud-python
6
+ Project-URL: Repository, https://github.com/markcassidyconsulting/ordercloud-python
7
+ Project-URL: Changelog, https://github.com/markcassidyconsulting/ordercloud-python/blob/main/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/markcassidyconsulting/ordercloud-python/issues
9
+ Author-email: Mark Cassidy Consulting <mark.cassidy@markcassidyconsulting.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: api,async,commerce,ecommerce,ordercloud,pydantic,sdk,sitecore
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Framework :: Pydantic :: 2
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Internet :: WWW/HTTP
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.10
26
+ Requires-Dist: httpx>=0.28.1
27
+ Requires-Dist: pydantic>=2.13.0
28
+ Provides-Extra: codegen
29
+ Requires-Dist: jinja2>=3.1.6; extra == 'codegen'
30
+ Provides-Extra: dev
31
+ Requires-Dist: mypy>=1.20.1; extra == 'dev'
32
+ Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
33
+ Requires-Dist: pytest-cov>=7.1.0; extra == 'dev'
34
+ Requires-Dist: pytest>=9.0.3; extra == 'dev'
35
+ Requires-Dist: respx>=0.23.1; extra == 'dev'
36
+ Requires-Dist: ruff>=0.15.10; extra == 'dev'
37
+ Provides-Extra: examples
38
+ Requires-Dist: python-dotenv>=1.2.2; extra == 'examples'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # ordercloud-python
42
+
43
+ [![CI](https://github.com/markcassidyconsulting/ordercloud-python/actions/workflows/ci.yml/badge.svg)](https://github.com/markcassidyconsulting/ordercloud-python/actions/workflows/ci.yml)
44
+ [![CodeQL](https://github.com/markcassidyconsulting/ordercloud-python/actions/workflows/codeql.yml/badge.svg)](https://github.com/markcassidyconsulting/ordercloud-python/actions/workflows/codeql.yml)
45
+ [![codecov](https://codecov.io/gh/markcassidyconsulting/ordercloud-python/graph/badge.svg)](https://codecov.io/gh/markcassidyconsulting/ordercloud-python)
46
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/markcassidyconsulting/ordercloud-python/badge)](https://scorecard.dev/viewer/?uri=github.com/markcassidyconsulting/ordercloud-python)
47
+ ![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)
48
+ [![PyPI](https://img.shields.io/pypi/v/ordercloud-python)](https://pypi.org/project/ordercloud-python/)
49
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
50
+
51
+ A fully typed, async-first Python SDK for [Sitecore OrderCloud](https://ordercloud.io).
52
+
53
+ **Complete API coverage** — all 632 operations across 60 resources, generated from the official OpenAPI spec. Built for modern Python:
54
+
55
+ - **Async and sync clients** — `async with OrderCloudClient(...)` or `with SyncOrderCloudClient(...)`. Same API shape, your choice of runtime.
56
+ - **Pydantic v2 models** — every API resource is a typed, validated model. snake_case fields, PascalCase aliases for API compatibility.
57
+ - **Typed extended properties** — `Product[MyXpModel]` gives you type-safe access to OrderCloud's `xp` fields.
58
+ - **Auto-pagination** — `async for product in paginate(client.products.list)` handles page iteration automatically.
59
+ - **Retry with backoff** — configurable retries on 429/5xx with exponential backoff and `Retry-After` support.
60
+ - **Middleware hooks** — intercept requests and responses for logging, metrics, or header injection.
61
+ - **Structured logging** — standard Python `logging` module, DEBUG/WARNING levels.
62
+ - **Full type annotations** — `py.typed` marker for downstream type checking with mypy, pyright, etc.
63
+ - **784 tests, 97% coverage** — 759 unit tests (mocked HTTP) + 25 integration tests (live sandbox).
64
+
65
+ ## Installation
66
+
67
+ ```bash
68
+ pip install ordercloud-python
69
+ ```
70
+
71
+ Requires Python 3.10+.
72
+
73
+ ## Quick Start
74
+
75
+ ### Async (default)
76
+
77
+ ```python
78
+ import asyncio
79
+ from ordercloud import OrderCloudClient
80
+
81
+ async def main():
82
+ async with OrderCloudClient.create(
83
+ client_id="YOUR_CLIENT_ID",
84
+ client_secret="YOUR_CLIENT_SECRET",
85
+ ) as client:
86
+ # List products
87
+ products = await client.products.list(page_size=10)
88
+ for p in products.items:
89
+ print(f"{p.id}: {p.name}")
90
+
91
+ # Create a product
92
+ from ordercloud.models import Product
93
+ product = await client.products.create(Product(
94
+ name="My Product",
95
+ active=True,
96
+ ))
97
+ print(f"Created: {product.id}")
98
+
99
+ asyncio.run(main())
100
+ ```
101
+
102
+ ### Sync
103
+
104
+ ```python
105
+ from ordercloud import SyncOrderCloudClient
106
+
107
+ with SyncOrderCloudClient.create(
108
+ client_id="YOUR_CLIENT_ID",
109
+ client_secret="YOUR_CLIENT_SECRET",
110
+ ) as client:
111
+ products = client.products.list(page_size=10)
112
+ for p in products.items:
113
+ print(f"{p.id}: {p.name}")
114
+ ```
115
+
116
+ The sync client wraps the async client internally — same features, same API shape, no `await`.
117
+
118
+ ## Configuration
119
+
120
+ | Parameter | Default | Description |
121
+ |-----------|---------|-------------|
122
+ | `client_id` | *(required)* | OAuth2 client ID |
123
+ | `client_secret` | `""` | OAuth2 client secret (empty for public clients) |
124
+ | `base_url` | `https://api.ordercloud.io/v1` | API base URL |
125
+ | `auth_url` | `https://auth.ordercloud.io/oauth/token` | OAuth2 token endpoint |
126
+ | `scopes` | `["FullAccess"]` | OAuth2 scopes to request |
127
+ | `timeout` | `30.0` | HTTP request timeout (seconds) |
128
+ | `max_retries` | `0` | Max retries on 429/5xx (0 = disabled) |
129
+ | `retry_backoff` | `0.5` | Base delay in seconds for exponential backoff |
130
+
131
+ ### Regional Environments
132
+
133
+ | Environment | API Base URL | Auth URL |
134
+ |-------------|-------------|----------|
135
+ | US Production | `https://api.ordercloud.io/v1` | `https://auth.ordercloud.io/oauth/token` |
136
+ | US Sandbox | `https://sandboxapi.ordercloud.io/v1` | `https://sandboxauth.ordercloud.io/oauth/token` |
137
+ | Europe West Production | `https://westeurope-production.ordercloud.io/v1` | `https://westeurope-production-auth.ordercloud.io/oauth/token` |
138
+ | Europe West Sandbox | `https://westeurope-sandbox.ordercloud.io/v1` | `https://westeurope-sandbox-auth.ordercloud.io/oauth/token` |
139
+ | Australia East Production | `https://australiaeast-production.ordercloud.io/v1` | `https://australiaeast-production-auth.ordercloud.io/oauth/token` |
140
+ | Japan East Production | `https://japaneast-production.ordercloud.io/v1` | `https://japaneast-production-auth.ordercloud.io/oauth/token` |
141
+
142
+ ## Typed Extended Properties (xp)
143
+
144
+ OrderCloud models support extended properties (`xp`) — arbitrary JSON attached to any resource. By default, `xp` is `dict[str, Any]`. You can type it with a Pydantic model:
145
+
146
+ ```python
147
+ from pydantic import BaseModel
148
+ from ordercloud.models import Product
149
+
150
+ class MyProductXp(BaseModel):
151
+ color: str
152
+ weight_kg: float
153
+
154
+ # Create with typed xp
155
+ product = Product[MyProductXp](
156
+ name="Widget",
157
+ xp=MyProductXp(color="red", weight_kg=1.5),
158
+ )
159
+ product.xp.color # str, not Any
160
+
161
+ # Deserialise with typed xp (API responses use PascalCase — the SDK handles both)
162
+ data = {"Name": "Widget", "xp": {"color": "blue", "weight_kg": 2.0}}
163
+ product = Product[MyProductXp].model_validate(data)
164
+ product.xp.color # "blue"
165
+ ```
166
+
167
+ Unparameterized usage (`Product(xp={"anything": True})`) still works — fully backward compatible. PascalCase field names are accepted as aliases for construction and deserialization (e.g. `Product(Name="Widget")` still works), but snake_case is the canonical Python form.
168
+
169
+ ## Auto-Pagination
170
+
171
+ Iterate through all pages automatically:
172
+
173
+ ```python
174
+ from ordercloud import paginate
175
+
176
+ # Async
177
+ async for product in paginate(client.products.list, search="widget"):
178
+ print(product.name)
179
+
180
+ # Works with positional args too
181
+ async for order in paginate(client.orders.list, OrderDirection.Incoming):
182
+ print(order.id)
183
+ ```
184
+
185
+ For the sync client:
186
+
187
+ ```python
188
+ from ordercloud import paginate_sync
189
+
190
+ for product in paginate_sync(client.products.list, search="widget"):
191
+ print(product.name)
192
+ ```
193
+
194
+ ## Retry Logic
195
+
196
+ Enable automatic retries on transient failures (429 rate limit, 5xx server errors):
197
+
198
+ ```python
199
+ client = OrderCloudClient.create(
200
+ client_id="...",
201
+ client_secret="...",
202
+ max_retries=3, # Retry up to 3 times
203
+ retry_backoff=0.5, # 0.5s, 1s, 2s exponential backoff
204
+ )
205
+ ```
206
+
207
+ Respects `Retry-After` headers. Never retries on 4xx client errors (400, 401, 403, 404, etc.).
208
+
209
+ ## Structured Logging
210
+
211
+ The SDK logs via Python's standard `logging` module under the `ordercloud` logger:
212
+
213
+ ```python
214
+ import logging
215
+ logging.basicConfig(level=logging.DEBUG)
216
+
217
+ # Or configure just the SDK logger
218
+ logging.getLogger("ordercloud").setLevel(logging.DEBUG)
219
+ ```
220
+
221
+ | Level | What's logged |
222
+ |-------|--------------|
223
+ | `DEBUG` | Every request (`Request: GET /products`) and response (`Response: GET /products 200`) |
224
+ | `WARNING` | Retry attempts with status code and backoff delay |
225
+
226
+ ## Middleware Hooks
227
+
228
+ Register hooks to intercept requests and responses:
229
+
230
+ ```python
231
+ from ordercloud import RequestContext, ResponseContext
232
+
233
+ async def add_correlation_id(ctx: RequestContext) -> None:
234
+ ctx.headers["X-Correlation-ID"] = generate_id()
235
+
236
+ async def log_timing(ctx: ResponseContext) -> None:
237
+ print(f"{ctx.request.method} {ctx.request.path} -> {ctx.response.status_code}")
238
+
239
+ client.add_before_request(add_correlation_id)
240
+ client.add_after_response(log_timing)
241
+ ```
242
+
243
+ Before-request hooks receive a mutable `RequestContext` — modify `headers`, `params`, or `json` before the request is sent. After-response hooks receive a `ResponseContext` with the request details and response. Hooks are called on every attempt, including retries.
244
+
245
+ ## API Coverage
246
+
247
+ The SDK covers **all 60 resources** and **632 operations** in the OrderCloud API. Models and resource clients are generated from the official OpenAPI v3 spec (version 1.0.445).
248
+
249
+ ### Core Commerce
250
+
251
+ | Resource | Operations | Highlights |
252
+ |----------|-----------|------------|
253
+ | Products | 18 | CRUD, variants, specs, suppliers, assignments |
254
+ | Orders | 29 | CRUD, submit, approve, decline, cancel, complete, forward, split, ship, promotions |
255
+ | Line Items | 9 | CRUD, shipping address management, cross-order listing |
256
+ | Cart | 37 | Full shopping cart lifecycle, checkout, payments, promotions |
257
+ | Bundles | 12 | CRUD, product/catalog assignments |
258
+ | Catalogs | 15 | CRUD, product/bundle/category assignments |
259
+ | Categories | 15 | CRUD, hierarchical with depth control, assignments |
260
+
261
+ ### Buyers & Users
262
+
263
+ | Resource | Operations | Highlights |
264
+ |----------|-----------|------------|
265
+ | Buyers | 7 | CRUD, seller relationships |
266
+ | Buyer Groups | 6 | CRUD |
267
+ | Users | 11 | CRUD, access tokens, move, cross-buyer listing |
268
+ | User Groups | 9 | CRUD, user assignments |
269
+ | Me | 80 | Full buyer-perspective API (addresses, orders, products, subscriptions, etc.) |
270
+ | Admin Users | 8 | CRUD, token revocation, account unlock |
271
+ | Admin User Groups | 9 | CRUD, user assignments |
272
+
273
+ ### Pricing & Promotions
274
+
275
+ | Resource | Operations | Highlights |
276
+ |----------|-----------|------------|
277
+ | Price Schedules | 8 | CRUD, price breaks |
278
+ | Promotions | 9 | CRUD, assignments |
279
+ | Discounts | 9 | CRUD, assignments |
280
+ | Specs | 15 | CRUD, options, product assignments |
281
+
282
+ ### Fulfillment
283
+
284
+ | Resource | Operations | Highlights |
285
+ |----------|-----------|------------|
286
+ | Shipments | 12 | CRUD, items, ship-from/ship-to addresses |
287
+ | Payments | 7 | CRUD, transactions |
288
+ | Order Returns | 14 | CRUD, submit, approve, decline, complete, cancel |
289
+
290
+ ### Organisation & Security
291
+
292
+ | Resource | Operations | Highlights |
293
+ |----------|-----------|------------|
294
+ | Suppliers | 9 | CRUD, buyer relationships |
295
+ | Security Profiles | 9 | CRUD, assignments |
296
+ | API Clients | 15 | CRUD, secrets, assignments |
297
+ | Addresses | 9 | CRUD, assignments |
298
+ | Cost Centers | 9 | CRUD, assignments |
299
+ | Credit Cards | 9 | CRUD, assignments |
300
+ | Spending Accounts | 9 | CRUD, assignments |
301
+
302
+ ### Integrations & Infrastructure
303
+
304
+ | Resource | Operations | Highlights |
305
+ |----------|-----------|------------|
306
+ | Webhooks | 6 | CRUD |
307
+ | Integration Events | 10 | CRUD, calculate, estimate shipping |
308
+ | Message Senders | 11 | CRUD, assignments, CC listeners |
309
+ | Subscriptions | 6 | CRUD |
310
+ | Entity Syncs | 40 | Full sync infrastructure |
311
+ | Delivery Configurations | 6 | CRUD |
312
+ | Inventory Records | 18 | CRUD, variant records, assignments |
313
+
314
+ ## Usage Examples
315
+
316
+ ### Products
317
+
318
+ ```python
319
+ # List with search and pagination
320
+ products = await client.products.list(
321
+ search="widget",
322
+ search_on="Name,Description",
323
+ sort_by="Name",
324
+ page=1,
325
+ page_size=20,
326
+ )
327
+ print(f"Found {products.meta.total_count} products")
328
+
329
+ # Get by ID
330
+ product = await client.products.get("my-product-id")
331
+
332
+ # Create
333
+ from ordercloud.models import Product
334
+ product = await client.products.create(Product(
335
+ id="my-product",
336
+ name="Widget",
337
+ description="A fine widget",
338
+ active=True,
339
+ ))
340
+
341
+ # Update (PUT — full replace)
342
+ product = await client.products.save("my-product", Product(
343
+ name="Updated Widget",
344
+ active=True,
345
+ ))
346
+
347
+ # Patch (partial update)
348
+ product = await client.products.patch("my-product", {"Description": "An even finer widget"})
349
+
350
+ # Delete
351
+ await client.products.delete("my-product")
352
+ ```
353
+
354
+ ### Orders
355
+
356
+ ```python
357
+ from ordercloud.models import Order, OrderDirection
358
+
359
+ # List incoming orders
360
+ orders = await client.orders.list(OrderDirection.Incoming, page_size=50)
361
+
362
+ # Create an outgoing order
363
+ order = await client.orders.create(
364
+ OrderDirection.Outgoing,
365
+ Order(comments="Rush delivery"),
366
+ )
367
+
368
+ # Order workflow
369
+ order = await client.orders.submit(OrderDirection.Outgoing, order.id)
370
+ order = await client.orders.approve(OrderDirection.Incoming, order.id)
371
+ order = await client.orders.complete(OrderDirection.Incoming, order.id)
372
+ ```
373
+
374
+ ### Line Items
375
+
376
+ ```python
377
+ from ordercloud.models import LineItem, OrderDirection
378
+
379
+ # Add a line item to an order
380
+ line_item = await client.line_items.create(
381
+ OrderDirection.Outgoing, "order-id",
382
+ LineItem(product_id="my-product", quantity=3),
383
+ )
384
+
385
+ # List line items on an order
386
+ line_items = await client.line_items.list(OrderDirection.Outgoing, "order-id")
387
+ for li in line_items.items:
388
+ print(f" {li.product_id} x{li.quantity}")
389
+ ```
390
+
391
+ ### Catalogs and Categories
392
+
393
+ ```python
394
+ from ordercloud.models import Catalog, Category
395
+
396
+ # Create a catalog
397
+ catalog = await client.catalogs.create(Catalog(
398
+ name="Spring Collection",
399
+ active=True,
400
+ ))
401
+
402
+ # Create a category within it
403
+ category = await client.categories.create(catalog.id, Category(
404
+ name="New Arrivals",
405
+ active=True,
406
+ ))
407
+
408
+ # List categories (with depth control)
409
+ categories = await client.categories.list(catalog.id, depth="all")
410
+ ```
411
+
412
+ ### Filtering
413
+
414
+ All `list()` methods accept a `filters` dict for server-side filtering:
415
+
416
+ ```python
417
+ # Products with Active=true and Name starting with "Widget"
418
+ products = await client.products.list(filters={
419
+ "Active": True,
420
+ "Name": "Widget*",
421
+ })
422
+
423
+ # Orders with Total > 100
424
+ orders = await client.orders.list(filters={"Total": ">100"})
425
+ ```
426
+
427
+ ## Error Handling
428
+
429
+ ```python
430
+ from ordercloud import OrderCloudError, AuthenticationError
431
+
432
+ try:
433
+ product = await client.products.get("nonexistent")
434
+ except AuthenticationError as e:
435
+ # 401 or 403
436
+ print(f"Auth failed: {e}")
437
+ except OrderCloudError as e:
438
+ # Any other API error (4xx/5xx)
439
+ print(f"API error {e.status_code}: {e}")
440
+ for error in e.errors:
441
+ print(f" {error.error_code}: {error.message}")
442
+ ```
443
+
444
+ ## Code Generation
445
+
446
+ Models and resource clients are generated from the OrderCloud OpenAPI v3 spec using the included codegen tool:
447
+
448
+ ```bash
449
+ pip install -e ".[codegen]"
450
+ python -m tools.codegen --spec path/to/ordercloud-openapi-v3.json --output src/ordercloud
451
+ ```
452
+
453
+ The codegen pipeline: **OpenAPI JSON** -> parser -> intermediate representation -> transformer -> Jinja2 templates -> Python source -> ruff format. Hand-written infrastructure (`shared.py`, `base.py`, `auth.py`, `http.py`, `config.py`, `errors.py`, `middleware.py`, `sync_client.py`) is preserved — only model and resource files are generated.
454
+
455
+ ## Development
456
+
457
+ ```bash
458
+ git clone https://github.com/markcassidyconsulting/ordercloud-python.git
459
+ cd ordercloud-python
460
+ pip install -e ".[dev,examples,codegen]"
461
+ ```
462
+
463
+ ### Running Tests
464
+
465
+ ```bash
466
+ # Unit tests only (mocked HTTP, no network calls — fast)
467
+ pytest tests/ --ignore=tests/integration
468
+
469
+ # Unit tests with coverage
470
+ pytest tests/ --ignore=tests/integration --cov=ordercloud --cov-report=term-missing
471
+
472
+ # Lint and format
473
+ ruff check src/ tests/
474
+ ruff format --check src/ tests/
475
+
476
+ # Type checking
477
+ mypy src/
478
+ ```
479
+
480
+ ### Integration Tests
481
+
482
+ Integration tests run against a live OrderCloud sandbox and are **skipped automatically** when credentials are not set. They never run by accident.
483
+
484
+ **Setup:**
485
+
486
+ 1. Create a `.env` file at the repo root (gitignored):
487
+
488
+ ```env
489
+ ORDERCLOUD_TEST_CLIENT_ID=your-sandbox-client-id
490
+ ORDERCLOUD_TEST_CLIENT_SECRET=your-sandbox-client-secret
491
+ ORDERCLOUD_TEST_BASE_URL=https://sandboxapi.ordercloud.io/v1
492
+ ORDERCLOUD_TEST_AUTH_URL=https://sandboxauth.ordercloud.io/oauth/token
493
+ ```
494
+
495
+ 2. Run:
496
+
497
+ ```bash
498
+ pytest tests/integration/ -v
499
+ ```
500
+
501
+ The test suite is self-bootstrapping — it uses the SDK itself to create all test data from a single admin API client credential. All test resources use an `inttest-` ID prefix and are cleaned up automatically.
502
+
503
+ > **Why `ORDERCLOUD_TEST_*`?** The `TEST_` prefix prevents the integration tests from running against a production OrderCloud instance if you happen to have `ORDERCLOUD_CLIENT_ID` set in your environment for normal SDK usage.
504
+
505
+ ### Test Suite
506
+
507
+ 784 tests across 12 modules.
508
+
509
+ **Unit tests (759)** — mocked HTTP via [respx](https://lundberg.github.io/respx/), no network calls:
510
+
511
+ | Module | Tests | Purpose |
512
+ |--------|-------|---------|
513
+ | `test_auth.py` | 13 | OAuth2 token management |
514
+ | `test_http.py` | 16 | HTTP client, error parsing, retries |
515
+ | `test_models.py` | 28 | Model round-trips, enums, xp, ListPage |
516
+ | `test_resources.py` | 22 | Representative resource operations |
517
+ | `test_resource_coverage.py` | 632 | All 60 resources, all 632 operations |
518
+ | `test_sync_client.py` | 48 | Sync wrapper, pagination |
519
+
520
+ **Integration tests (25)** — live sandbox, skipped when credentials are absent:
521
+
522
+ | Module | Tests | Purpose |
523
+ |--------|-------|---------|
524
+ | `test_auth.py` | 4 | Client credentials grant, token caching |
525
+ | `test_crud.py` | 7 | Products, Buyers, Catalogs, Categories, Users |
526
+ | `test_pagination.py` | 3 | Auto-pagination, search, list metadata |
527
+ | `test_query_params.py` | 3 | Assignment lifecycle, DELETE with query params |
528
+ | `test_errors.py` | 5 | Error parsing, structured API errors |
529
+ | `test_sync_client.py` | 3 | Sync CRUD, pagination, errors |
530
+
531
+ **Coverage** (97% overall, 90% threshold enforced in CI):
532
+
533
+ | Module | Coverage |
534
+ |--------|----------|
535
+ | `auth.py` | 100% |
536
+ | `client.py` | 100% |
537
+ | `config.py` | 100% |
538
+ | `errors.py` | 100% |
539
+ | `http.py` | 97% |
540
+ | `middleware.py` | 100% |
541
+ | `sync_client.py` | 100% |
542
+ | `resources/base.py` | 100% |
543
+ | `models/shared.py` | 100% |
544
+ | All 37 model modules | 100% |
545
+
546
+ ## Contributing
547
+
548
+ Bug reports and feature requests are welcome via [GitHub Issues](https://github.com/markcassidyconsulting/ordercloud-python/issues). If you're interested in the internals, the codegen pipeline in `tools/codegen/` is a good starting point. See the [Changelog](CHANGELOG.md) for release history.
549
+
550
+ ## License
551
+
552
+ MIT
@@ -0,0 +1,114 @@
1
+ ordercloud/__init__.py,sha256=qMYkRQaHDGIQzjVOca0xbRBxaA0SB6Dv3ULJvZGHips,977
2
+ ordercloud/auth.py,sha256=GHMnOmT8EFu9pEHOtYokBw2eG1_Vqqq2LPe4cTplg-k,4977
3
+ ordercloud/client.py,sha256=QH_kDr9mlM9PVu74-29oZ4Whe-zQLoMdnJWRQXET22E,10250
4
+ ordercloud/config.py,sha256=IFJ_1LgK6gxq_W3GXeGgBRh2fkALHbvK0QIVGufDXQU,1460
5
+ ordercloud/errors.py,sha256=7AGWlqQIy5apGuseyYrDLqlkr5YxE8WgV3igQztm2VI,1291
6
+ ordercloud/http.py,sha256=iSu7QKUbH-8roDTH_4O9qmgUvs5pAEjq7nZmyBz5dms,7514
7
+ ordercloud/middleware.py,sha256=mLkrkGZDbb4sMA9RC-rRJHw05cjCqOiFX3tol01LRR0,1807
8
+ ordercloud/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ ordercloud/sync_client.py,sha256=H6bHKnpiOGYIlYOmwK9DYGCwRuIQxs9Sgmhgnt4v1xg,5519
10
+ ordercloud/models/__init__.py,sha256=RLPINICNHal4ifOqw86cd-99gPfsd6AKIWYgQ2vYgEQ,5650
11
+ ordercloud/models/address.py,sha256=NDIJNDE_aPlCGtTypY2GfNn-xG4E4_GOgTst2oMAffM,1436
12
+ ordercloud/models/api_client.py,sha256=Rvme1dspLvhj9nXomrkOahLePXvDDT77ta-45w2DsC8,5779
13
+ ordercloud/models/approval.py,sha256=kxD-Qgg5y-dYTi0mKQ656ou0Iszddhg1ZD-lH2KGWBE,2481
14
+ ordercloud/models/assignments.py,sha256=0Zk_nz8_4DSOeeKF5adeWLU4sozJ4MrYlTDfMbuoaLE,12446
15
+ ordercloud/models/auth_models.py,sha256=-LuKaUG0SjVXiS5XwbjyBL4bAWT6hXuW2F2JRjGs7uc,2794
16
+ ordercloud/models/bundle.py,sha256=5UrdUvyGUc_i-5NA1MJFA980yUtqSkYlJv2LZGGOWvM,1109
17
+ ordercloud/models/buyer.py,sha256=lmTqZq4aPKJvQ-tYfdkHTHfnmoSOSld4EbIptSTSEcU,12052
18
+ ordercloud/models/catalog.py,sha256=Olh9go83O5MJrxDq6H302ljfLbfIiYRWjeRodLuIof0,1100
19
+ ordercloud/models/category.py,sha256=lYQR5hOplel8I1nh5siceTVe95y5Vcggaq5Iq5g33Go,1235
20
+ ordercloud/models/cost_center.py,sha256=gtbYeT2qLu97x1QhSheYg8UERh2b1y5X8m4fVi8cEeY,666
21
+ ordercloud/models/credit_card.py,sha256=tMKifoKBsuDqEtg5yyhuMCYMsy_iq7DSUAu1FUwgcA8,1170
22
+ ordercloud/models/delivery.py,sha256=tHnw9V0QEVgtpHKESrxsW64DMroB_qR3jKnFveRG79E,8041
23
+ ordercloud/models/discount.py,sha256=KHA83fBLSzPSzctiW9_71HUGHOks8tquAZVr025Yzx0,2212
24
+ ordercloud/models/integration.py,sha256=TeTcUmrS49xJvP2JkNA8d1gbUEpMGIlIi6xqfV9DhG0,2806
25
+ ordercloud/models/inventory_record.py,sha256=zq0-sKk4Vox6Kp5lHKM1I4jayj7y9ibFy2LcYSlLZd8,2262
26
+ ordercloud/models/line_item.py,sha256=lep7bKF-5fgqoaoSR0Ck8E9bkSX8bcSiahfilSs5NFk,5045
27
+ ordercloud/models/line_item_types.py,sha256=xlFO3Xxt2wnD_OzIVGRNqsazvRTVsJ52M8kGLXJroBs,2913
28
+ ordercloud/models/message_sender.py,sha256=t-E8dJC00_4mgKMgx2eMcsF6ysnHTIirXwy860IlTzo,3181
29
+ ordercloud/models/misc.py,sha256=EQbyxTTtCIZ0FCLzneiU0EVuyeG2B4cI5jLDsNGPHmw,8864
30
+ ordercloud/models/open_id_connect.py,sha256=G_IAYeouhgg4tEbt3mv9X6byPDHooYpcAW9c6GwH99U,3212
31
+ ordercloud/models/order.py,sha256=sKeF5TpabobHttIh-QXt5kqKjgp1mWeWyZXhcEQP5oo,22317
32
+ ordercloud/models/order_return.py,sha256=XWXolExpfrnnnGQXNHO3b-NbTGei4CBZWp8Kr05LOk0,3714
33
+ ordercloud/models/payment.py,sha256=J2T3Us648bGDfer5nU5W6MGI6JwnMx4IfkMskrdBrRY,3319
34
+ ordercloud/models/price_schedule.py,sha256=7lmI_UFfgmAdW1S2qAjUzNMti1WJHC4hoRm6lAlI0j8,4100
35
+ ordercloud/models/product.py,sha256=HeoxoLl2zEkQkM_TBM97WkpJhJNqHijKboNcrxEw7z4,9631
36
+ ordercloud/models/product_collection.py,sha256=SPm1oLvSXW7HKDZSWKub-cgnBrC4qE_HCn7U-I7Qujs,8584
37
+ ordercloud/models/promotion.py,sha256=AlYkprse3MwkgJWnw9QUA4MkHd4fOXoeCy8wgARbjR0,19247
38
+ ordercloud/models/security.py,sha256=zmJIAbN_abPzQvnmLNyazLhop1C8lZ-cONvU3oWTJwE,4615
39
+ ordercloud/models/shared.py,sha256=XSm3nmkHkMnrF0Ej6LqV9h5p4byqwVOIVkAVk7xa9mA,3967
40
+ ordercloud/models/shipment.py,sha256=5mGj-PP5eWzndQofsTt6Uu8OeT4BZIfIbEcItLb89Ac,5480
41
+ ordercloud/models/spec.py,sha256=DWW77Uq275gB0ydbfSEhRtnNWlU_to9CnjfldSvNkPQ,2758
42
+ ordercloud/models/spending_account.py,sha256=L9SbjxWx_7NmC9Le87zup9aNdv_TvQ6Zyk_7l0i_e7A,1026
43
+ ordercloud/models/subscription.py,sha256=tkHNe779oyv8wjzCFy8xu4Og76mMau7Of7LrpckMX60,5550
44
+ ordercloud/models/supplier.py,sha256=qXK6CCxDvqZA2oKFbaK6ZasGyduN9u1vcWUSpvZd2b4,1308
45
+ ordercloud/models/sync.py,sha256=jb1BO_go7abNsgCDiw1CGlJmIPdhW_hH5uNJRr5rWr4,4191
46
+ ordercloud/models/user.py,sha256=PeCQatCVmXBDrLbUoloI8R_76bFR0LoR6KjkkuB_9qs,7933
47
+ ordercloud/models/user_group.py,sha256=L1JT0szpShjaNy7izzFewChAdbJtOfPDq9-Hk640i9o,662
48
+ ordercloud/models/webhook.py,sha256=aP8bmxhqG9-QJbdcZfD2w6yNhK__x1Wu3mIBvFqYmSA,2619
49
+ ordercloud/resources/__init__.py,sha256=9TvEIbXpQBRqzBaqcdmr8LPxduxR069TJ66U4H_0n7Q,3929
50
+ ordercloud/resources/addresses.py,sha256=5C8AfRnF4g-RFXXh20haP-OccJSM4Jzt9VCGoYCSPzw,7540
51
+ ordercloud/resources/admin_addresses.py,sha256=bIneIPsE6VQH3AuWxMXUCvdSVHLgKOxnkrHPScwSnb0,3818
52
+ ordercloud/resources/admin_user_groups.py,sha256=4Y_Nj12QjzhNuAdTO8GTcZL1q18tAnOAnImJPXSxxbo,5965
53
+ ordercloud/resources/admin_users.py,sha256=9Fc7pGCvsD-surhU0gqRL2vmblUwl2td8nz75-yb5Tk,4198
54
+ ordercloud/resources/api_clients.py,sha256=i5riZ2l-mvliO1BN_xSE56Z8J9V9Z6FpI_vYBO-x_iY,10267
55
+ ordercloud/resources/approval_rules.py,sha256=R2k6tL38B2i9w5u5VG2uUsQHH1m3t8oF8gGsAsKZ4fE,4616
56
+ ordercloud/resources/base.py,sha256=MSVFOfnACKnFvoYo2nXZ_oDxbPR6Bj9zUOjZ8hKrl-o,4851
57
+ ordercloud/resources/bundle_line_items.py,sha256=qq8g9La0XAvfUKTtx4sjUdittiib0ocnQzi91OztAvE,1763
58
+ ordercloud/resources/bundle_subscription_items.py,sha256=VDZPqej5trH64S-q7d296hURMKC2soUsDG2RV_rbG80,1578
59
+ ordercloud/resources/bundles.py,sha256=h8R1ohh9r3QnBIyTMKf6eh5ei8EgRhDgLcgQBPBIZ0g,9295
60
+ ordercloud/resources/buyer_groups.py,sha256=NEI84cCSFNabbHuhMJIumkCJ7V0J2bcnSNv_tfggLJo,3910
61
+ ordercloud/resources/buyers.py,sha256=my6Cr5Ly2uMgLZfFS9_1HMArY58kLNtTA11LPzgMG-Y,5112
62
+ ordercloud/resources/cart.py,sha256=6ZpkbduzfzVODOVFbu1f4BhDkhmXKFDiSN80CT94qwc,18137
63
+ ordercloud/resources/catalogs.py,sha256=x76LG649kUDkWOIaEtXPWj9TlXGrrFii2MwOaOMm_sQ,10257
64
+ ordercloud/resources/categories.py,sha256=O88wm-Be_vl8KQFUOEElnr2DU3GE7Dg0kxO4ImpMu9g,13353
65
+ ordercloud/resources/cost_centers.py,sha256=JiPyIYLp5AchmXwDr5LFWXh6piKk9TM-63CmhsxDmYk,7294
66
+ ordercloud/resources/credit_cards.py,sha256=rlHVs2aYsaC7trnHL9ykQqYNWfJcAq6grDioRNXYEEA,7443
67
+ ordercloud/resources/delivery_configurations.py,sha256=AKhH-MAPR5KBCCNxPB3UktGxN3K_cTIe-ldBBfgAG7s,4375
68
+ ordercloud/resources/discounts.py,sha256=TWZPSic_r3sZ4g5CrXUQGHzy5o1MemUFakndDieCy-A,6551
69
+ ordercloud/resources/entity_syncs.py,sha256=W4uxQBy9lht224g997VARVmaSSiqi_50PeHhSx--9kI,17502
70
+ ordercloud/resources/error_configs.py,sha256=wNM0gQOLexgMBb9wHP39TzPSNd6WAViUE76xKHCTVtc,1872
71
+ ordercloud/resources/forgotten_credentials.py,sha256=xxc3gZAOxd5kTjVJp0k6OoedoInyhO7HvExlwuWhU90,2465
72
+ ordercloud/resources/group_orders.py,sha256=vP5pKXIu_semaw08PsQhHDuGxW2bUFK0gFfD0YCSdyU,741
73
+ ordercloud/resources/impersonation_configs.py,sha256=5BZuM2YZH5fa5htL2m8Nc03NM7v7G3mTquT4ehJNrLE,4524
74
+ ordercloud/resources/incrementors.py,sha256=K3HFvVM1bb4ysAMXP8uaG642roRoLR9h6aQiiXHMdEw,3992
75
+ ordercloud/resources/integration_events.py,sha256=XjuSC_TLszYmu0Q6cve1J8e3VU905s3Y2LPAm3pTMaw,6698
76
+ ordercloud/resources/inventory_integrations.py,sha256=CGcv8kldBh8mZpDzHwKJGKkJuI9kp90dJY7b3vVjOQc,1917
77
+ ordercloud/resources/inventory_records.py,sha256=RJz98GOEDa6eVOZb66zmmInNTwYsmQ32qOIpf_QSvas,17312
78
+ ordercloud/resources/line_items.py,sha256=OdzdHK2Reb40KfSWeLTYnf1xblcW4JQdDibSv2zP7Qg,9162
79
+ ordercloud/resources/locales.py,sha256=kIiTO7SE1M-9Z5KPbr-CgME0OwUdvPyUKs_WmC8c8vs,6395
80
+ ordercloud/resources/me.py,sha256=FG5kJwnmWVykQMsTf1qqyA3GaLQwe7FUP3NeGQ04KDo,68671
81
+ ordercloud/resources/message_senders.py,sha256=oGqP5pCe_vXOwTqJKqRd5rAzEXZSswRtN5PGOZbGTxE,9567
82
+ ordercloud/resources/open_id_connects.py,sha256=EZx531s-1rT3QntH5skgUMz2vTMA8ny3SfW78UII7Ys,4301
83
+ ordercloud/resources/order_returns.py,sha256=hGdnuDivv8GpoY2sO9kkHcf6nTfwGvHMs1BGoHlN0BY,9805
84
+ ordercloud/resources/order_syncs.py,sha256=By97hfffrMzqblkCiEiaTWbPjgMT342rz7YQvj9JJQo,1745
85
+ ordercloud/resources/orders.py,sha256=PDWOb-FaypqqeQtt1ji6sNA2JaR7Ob7fWkmG8nWA230,23579
86
+ ordercloud/resources/payments.py,sha256=FtJ03Q0jUS0JlfiXumA4trz4syp_1LTk6i_rp-ZELJM,5763
87
+ ordercloud/resources/price_schedules.py,sha256=epITuZJlWD21CHJ-fJg-PXQbSN31NfdrKQW5JPPkF38,5275
88
+ ordercloud/resources/product_collections.py,sha256=K4IDb6B1Oj-zB7vxUDwwEQNP15j02t2lvPF-jH9FSAk,4475
89
+ ordercloud/resources/product_facets.py,sha256=KUOUx_doxGozLFKyGcWTtbC78bhG_eo3AgP4FjUqp0I,4025
90
+ ordercloud/resources/product_syncs.py,sha256=8bKrcFcLM-zkKI8S6T6EaqWJWpYKQ1v9GgsCr4CWxqU,2196
91
+ ordercloud/resources/products.py,sha256=zskvsf9ykbVb-Y915Fj5fFke2SyGIMFrCp_l45hbR8M,15541
92
+ ordercloud/resources/promotion_integrations.py,sha256=rzJnvScjNHS2dv01tyl_KWwBsquyeetZMDMTuMrkozY,1897
93
+ ordercloud/resources/promotions.py,sha256=7sSKSqve6ZESZLxD2nWj0c-DK-BoiK9XjUQ_HWQNumc,6687
94
+ ordercloud/resources/security_profiles.py,sha256=cRETxniHIJ_Py4iFt13KBIq9PGWGf0z9QccoMLDdnuk,8034
95
+ ordercloud/resources/seller_approval_rules.py,sha256=B8yC0CCoR2YQQBPY0HRQQmLyBbB3g2E6S9HvJ--Yj8c,4341
96
+ ordercloud/resources/shipments.py,sha256=vTqtxa7yMDesEPEZSurRaw9Tt2ZQp7EVq-uPC13Oqio,7852
97
+ ordercloud/resources/specs.py,sha256=yTLnHcGirlSHYE_v_4H4Hx20D4T-oIbmg0I-V9NyE2U,9755
98
+ ordercloud/resources/spending_accounts.py,sha256=A_xh3HHDHGp-9voPjw4LGNhR4_Wbh0b2B_MnoVxUaKA,7937
99
+ ordercloud/resources/subscription_integrations.py,sha256=E5wzTBGaolqfykzgz6r6v4tPTdzErKDLX_byQEAF3Ak,1994
100
+ ordercloud/resources/subscription_items.py,sha256=WH1V9g_Q-19FYtIM9vzNcmdyLXRiRdDXFKdKMJ22G9E,4750
101
+ ordercloud/resources/subscriptions.py,sha256=IHmkPXJZERilybNWJSSM1ofFoh1_8PLIkv7jiu4zRz4,4065
102
+ ordercloud/resources/supplier_addresses.py,sha256=fL76m3IDsLTdh5i9ya3wLrPP461DY8c6R-hTOTD1I9I,4459
103
+ ordercloud/resources/supplier_user_groups.py,sha256=xhHZjdPYnactPUswD631kpMt10FSv4D6svwZ6fODalM,6935
104
+ ordercloud/resources/supplier_users.py,sha256=sTsfU8NR_KqxDz_dlp37h39o-HAiGIAVWeMfNo5KbTc,5127
105
+ ordercloud/resources/suppliers.py,sha256=jwzvrVNQEubgyVgvLYuBLZQrbG7okmLOxc9DIV0p_1w,5944
106
+ ordercloud/resources/tracking_events.py,sha256=qEDlTGd7Ln2h6TW8qI1V9zMnjPOXHoVNBho9Ng4Y5j4,4124
107
+ ordercloud/resources/user_groups.py,sha256=VDbVFtce48Ar0uSlzNfFVRm-TM5j4youNzMnrnt08gU,6687
108
+ ordercloud/resources/users.py,sha256=viaOyufvl_iKQ9Txi9MZQyKcyooSsqi9IrQeWy_TQW0,7898
109
+ ordercloud/resources/webhooks.py,sha256=phzdD-oLerrHz1OeHoiBnAS_4dxBsiwXknjXkUoqL9E,3710
110
+ ordercloud/resources/xp_indices.py,sha256=h74UvkuR0HJahX_v5E6moUth1VwAo4cvnFvyhDrHAEg,2816
111
+ ordercloud_python-2026.4.1.dist-info/METADATA,sha256=CtXq6Ob8WYu6E-IAZOG3OIX41PbLTOfvnBMTu3z1YuA,19636
112
+ ordercloud_python-2026.4.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
113
+ ordercloud_python-2026.4.1.dist-info/licenses/LICENSE,sha256=x9gaXR_jrxgfZU27dgI3kUXDp9twvsZh-ZIzazdv3sk,1080
114
+ ordercloud_python-2026.4.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any