peddler 5.0.0.pre.8 → 5.0.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.
- checksums.yaml +4 -4
- data/README.md +77 -764
- data/lib/peddler/reports/vendor_real_time_sales/report.rb +1 -1
- data/lib/peddler/version.rb +1 -1
- data/sig/peddler/reports/vendor_real_time_sales.rbs +6 -6
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 497c9b25616dbeb253062deda4931a5126cc95589c62592d0dbff97a7472e4d6
|
|
4
|
+
data.tar.gz: 79b7eb41ffe20cd88468eb666c2273dc1c171070de181c622dacf308a000f05d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d03f0b0c3b45cf707f35fb9b9faf6dbdbdae299d9fc785e8573cd22cfa8e0c86605901b15a0c11924de2f9d6c5a918f4f7e58341a9445d185f1266f85a36058d
|
|
7
|
+
data.tar.gz: 6140e0f80ba6810d8f544bb96ee7016b1e6d6307a33b98e5f42b8df8dd1ede7079b80e9c06c1344b0bc31f05654cd620d2027fa4485b57def42d7e615def07fe
|
data/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[][build]
|
|
4
4
|
|
|
5
|
-
>
|
|
5
|
+
> AI Agents: See [llms.txt](llms.txt)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Peddler is a Ruby interface to the [Amazon Selling Partner API (SP-API)][api-docs]. The SP-API enables Amazon sellers and vendors to programmatically access their data on orders, shipments, payments, and more.
|
|
8
8
|
|
|
9
9
|
Peddler is automatically generated from the latest Open API models provided by Amazon.
|
|
10
10
|
|
|
@@ -18,20 +18,12 @@ To begin using the Amazon SP-API, you must [register as a developer][register-as
|
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
20
20
|
|
|
21
|
-
Add
|
|
22
|
-
|
|
23
|
-
```ruby
|
|
24
|
-
gem "peddler", "~> 5.0.0.pre.8"
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
And then execute:
|
|
28
|
-
|
|
29
|
-
```shell
|
|
30
|
-
bundle install
|
|
31
|
-
```
|
|
21
|
+
Add to your Gemfile.
|
|
32
22
|
|
|
33
23
|
## Usage
|
|
34
24
|
|
|
25
|
+
### Authorization
|
|
26
|
+
|
|
35
27
|
Set your LWA credentials in your environment.
|
|
36
28
|
|
|
37
29
|
```shell
|
|
@@ -39,14 +31,6 @@ export LWA_CLIENT_ID=<YOUR_CLIENT_ID>
|
|
|
39
31
|
export LWA_CLIENT_SECRET=<YOUR_CLIENT_SECRET>
|
|
40
32
|
```
|
|
41
33
|
|
|
42
|
-
Require the library.
|
|
43
|
-
|
|
44
|
-
```ruby
|
|
45
|
-
require "peddler"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
### Authorization
|
|
49
|
-
|
|
50
34
|
A seller or vendor [provides you a refresh token][authorization] to access their data on Amazon.
|
|
51
35
|
|
|
52
36
|
```ruby
|
|
@@ -56,7 +40,7 @@ response = Peddler::LWA.request(
|
|
|
56
40
|
refresh_token = response.parse.refresh_token
|
|
57
41
|
```
|
|
58
42
|
|
|
59
|
-
|
|
43
|
+
Use this to generate a temporary access token to authenticate individual requests.
|
|
60
44
|
|
|
61
45
|
```ruby
|
|
62
46
|
response = Peddler::LWA.request(
|
|
@@ -74,7 +58,7 @@ response = Peddler::LWA.request(
|
|
|
74
58
|
access_token = response.parse.access_token
|
|
75
59
|
```
|
|
76
60
|
|
|
77
|
-
|
|
61
|
+
In place of environment variables, you can set them directly when requesting the token.
|
|
78
62
|
|
|
79
63
|
```ruby
|
|
80
64
|
response = Peddler::LWA.request(
|
|
@@ -85,9 +69,9 @@ response = Peddler::LWA.request(
|
|
|
85
69
|
access_token = response.parse.access_token
|
|
86
70
|
```
|
|
87
71
|
|
|
88
|
-
Access tokens are valid for one hour. To optimize performance, cache
|
|
72
|
+
Access tokens are valid for one hour. To optimize performance, cache and reuse across calls.
|
|
89
73
|
|
|
90
|
-
|
|
74
|
+
For example,
|
|
91
75
|
|
|
92
76
|
```ruby
|
|
93
77
|
class Seller
|
|
@@ -103,30 +87,24 @@ end
|
|
|
103
87
|
|
|
104
88
|
### Rate limiting
|
|
105
89
|
|
|
106
|
-
Amazon's SP-API imposes [rate limits][rate-limits] on operations. Override the default
|
|
90
|
+
Amazon's SP-API imposes [rate limits][rate-limits] on operations. Override the default value by passing a `:rate_limit` parameter when calling an operation.
|
|
107
91
|
|
|
108
|
-
Provide an optional `:retries` argument when initializing an API to specify retry attempts if throttled. Default is 0 (no retries). If set
|
|
92
|
+
Provide an optional `:retries` argument when initializing an API to specify retry attempts if throttled. Default is 0 (no retries). If set, Peddler retries with exponential backoff.
|
|
109
93
|
|
|
110
94
|
```ruby
|
|
111
95
|
api = Peddler.orders_v0.new(aws_region, access_token, retries: 3)
|
|
112
|
-
api.get_orders(
|
|
113
|
-
marketplaceIds: ["ATVPDKIKX0DER"],
|
|
114
|
-
createdAfter: "2023-01-01T00:00:00Z"
|
|
115
|
-
)
|
|
96
|
+
api.get_orders("...": "...")
|
|
116
97
|
```
|
|
117
98
|
|
|
118
99
|
### Typed Responses
|
|
119
100
|
|
|
120
|
-
Peddler provides typed response parsing using the [Structure gem](https://github.com/hakanensari/structure), offering runtime type checking and better IDE support. Types are based on Ruby's [Data class](https://docs.ruby-lang.org/en/3.4/Data.html) and are lazy-loaded
|
|
101
|
+
Peddler provides typed response parsing using the [Structure gem](https://github.com/hakanensari/structure), offering runtime type checking and better IDE support. Types are based on Ruby's [Data class](https://docs.ruby-lang.org/en/3.4/Data.html) and are lazy-loaded.
|
|
121
102
|
|
|
122
103
|
```ruby
|
|
123
104
|
api = Peddler.orders.new(aws_region, access_token)
|
|
124
105
|
|
|
125
106
|
# Get orders with type-safe response
|
|
126
|
-
response = api.get_orders(
|
|
127
|
-
marketplaceIds: ["ATVPDKIKX0DER"],
|
|
128
|
-
createdAfter: "2023-01-01T00:00:00Z"
|
|
129
|
-
)
|
|
107
|
+
response = api.get_orders("...": "...")
|
|
130
108
|
|
|
131
109
|
# Use .parse to get typed Data objects
|
|
132
110
|
orders = response.parse.payload.orders # Returns array of Order Data objects
|
|
@@ -189,246 +167,74 @@ You can also simply use the latest version:
|
|
|
189
167
|
api = Peddler.<api_name>.new(aws_region, access_token, options)
|
|
190
168
|
```
|
|
191
169
|
|
|
192
|
-
|
|
170
|
+
Available APIs by category:
|
|
193
171
|
|
|
194
172
|
#### Orders and Financial APIs
|
|
195
173
|
|
|
196
|
-
- **Orders API
|
|
197
|
-
- **Finances API
|
|
198
|
-
- **Invoices API
|
|
199
|
-
- **Sales API
|
|
174
|
+
- **Orders API**: Retrieve and manage orders
|
|
175
|
+
- **Finances API**: Financial data, payments, refunds
|
|
176
|
+
- **Invoices API**: Manage billing invoices
|
|
177
|
+
- **Sales API**: Order metrics and sales data
|
|
200
178
|
|
|
201
179
|
```ruby
|
|
202
180
|
api = Peddler.orders.new(aws_region, access_token)
|
|
203
|
-
response = api.get_orders(
|
|
204
|
-
marketplaceIds: ["ATVPDKIKX0DER"],
|
|
205
|
-
createdAfter: "2023-01-01T00:00:00Z"
|
|
206
|
-
)
|
|
181
|
+
response = api.get_orders("...": "...")
|
|
207
182
|
orders = response.parse.payload.orders
|
|
208
|
-
order_id = orders.first.amazon_order_id
|
|
209
|
-
|
|
210
|
-
# Or use .to_h or .dig to parse response as a hash
|
|
211
|
-
orders = response.dig("payload", "orders")
|
|
212
|
-
order_id = response.dig("payload", "orders", 0, "amazonOrderId")
|
|
213
|
-
|
|
214
|
-
# For sandbox testing
|
|
215
|
-
api.sandbox.get_orders(
|
|
216
|
-
marketplaceIds: ["ATVPDKIKX0DER"],
|
|
217
|
-
createdAfter: "TEST_CASE_200"
|
|
218
|
-
)
|
|
219
183
|
```
|
|
220
184
|
|
|
221
185
|
#### Catalog and Listing APIs
|
|
222
186
|
|
|
223
|
-
- **Catalog Items API
|
|
224
|
-
- **Listings Items API
|
|
225
|
-
- **Listings Restrictions API
|
|
226
|
-
- **Product Type Definitions API
|
|
227
|
-
- **A+ Content API
|
|
228
|
-
- **Product Pricing API
|
|
229
|
-
- **Product Fees API
|
|
187
|
+
- **Catalog Items API**: Access Amazon's catalog data
|
|
188
|
+
- **Listings Items API**: Create and update listings
|
|
189
|
+
- **Listings Restrictions API**: Check listing eligibility
|
|
190
|
+
- **Product Type Definitions API**: Get schema requirements for listings
|
|
191
|
+
- **A+ Content API**: Create and manage enhanced marketing content
|
|
192
|
+
- **Product Pricing API**: Get pricing information
|
|
193
|
+
- **Product Fees API**: Retrieve fee estimates for products
|
|
230
194
|
|
|
231
195
|
```ruby
|
|
232
196
|
api = Peddler.catalog_items.new(aws_region, access_token)
|
|
233
|
-
response = api.get_catalog_item(
|
|
234
|
-
|
|
235
|
-
asin: "B08N5WRWNW"
|
|
236
|
-
)
|
|
237
|
-
response.parse.payload.asin # => "B08N5WRWNW"
|
|
238
|
-
|
|
239
|
-
# Search catalog items by identifier
|
|
240
|
-
response = api.search_catalog_items(
|
|
241
|
-
["ATVPDKIKX0DER"],
|
|
242
|
-
identifiers: "B08N5WRWNW",
|
|
243
|
-
identifiers_type: "ASIN"
|
|
244
|
-
)
|
|
245
|
-
search_results = response.parse
|
|
197
|
+
response = api.get_catalog_item("...": "...")
|
|
198
|
+
item = response.parse.payload
|
|
246
199
|
```
|
|
247
200
|
|
|
248
201
|
#### Fulfillment and Inventory APIs
|
|
249
202
|
|
|
250
|
-
- **Fulfillment Inbound API
|
|
251
|
-
- **Fulfillment Outbound API
|
|
252
|
-
- **FBA Inventory API
|
|
253
|
-
- **FBA Inbound Eligibility API
|
|
254
|
-
- **Merchant Fulfillment API
|
|
255
|
-
- **Easy Ship API
|
|
256
|
-
- **Shipping APIs
|
|
257
|
-
- **Replenishment API
|
|
258
|
-
- **Amazon Warehousing and Distribution API
|
|
259
|
-
- **Supply Sources API
|
|
260
|
-
- **Shipment Invoicing API
|
|
203
|
+
- **Fulfillment Inbound API**: Send inventory to FBA
|
|
204
|
+
- **Fulfillment Outbound API**: Create and track FBA orders
|
|
205
|
+
- **FBA Inventory API**: Manage FBA inventory quantities
|
|
206
|
+
- **FBA Inbound Eligibility API**: Check product eligibility for FBA
|
|
207
|
+
- **Merchant Fulfillment API**: Create shipping labels for self-fulfilled orders
|
|
208
|
+
- **Easy Ship API**: Manage Amazon's carrier service
|
|
209
|
+
- **Shipping APIs**: Create shipments and purchase shipping labels
|
|
210
|
+
- **Replenishment API**: Manage inventory replenishment
|
|
211
|
+
- **Amazon Warehousing and Distribution API**: Manage fulfillment warehousing
|
|
212
|
+
- **Supply Sources API**: Manage supply/inventory sources
|
|
213
|
+
- **Shipment Invoicing API**: Manage shipment-related invoices
|
|
261
214
|
|
|
262
215
|
```ruby
|
|
263
|
-
# FBA outbound example
|
|
264
216
|
api = Peddler.fulfillment_outbound.new(aws_region, access_token)
|
|
265
|
-
api.create_fulfillment_order(
|
|
266
|
-
body: {
|
|
267
|
-
sellerFulfillmentOrderId: "ORDER123",
|
|
268
|
-
displayableOrderId: "ORDER123",
|
|
269
|
-
displayableOrderDate: Time.now.iso8601,
|
|
270
|
-
shippingSpeedCategory: "Standard",
|
|
271
|
-
destinationAddress: {
|
|
272
|
-
name: "Customer Name",
|
|
273
|
-
addressLine1: "123 Main St",
|
|
274
|
-
city: "Seattle",
|
|
275
|
-
stateOrRegion: "WA",
|
|
276
|
-
postalCode: "98101",
|
|
277
|
-
countryCode: "US"
|
|
278
|
-
},
|
|
279
|
-
items: [
|
|
280
|
-
{
|
|
281
|
-
sellerSku: "SKU123",
|
|
282
|
-
sellerFulfillmentOrderItemId: "ITEM123",
|
|
283
|
-
quantity: 1
|
|
284
|
-
}
|
|
285
|
-
]
|
|
286
|
-
}
|
|
287
|
-
)
|
|
217
|
+
response = api.create_fulfillment_order(body: { "...": "..." })
|
|
288
218
|
```
|
|
289
219
|
|
|
290
220
|
#### Data Management APIs
|
|
291
221
|
|
|
292
|
-
- **Feeds API
|
|
293
|
-
- **Reports API
|
|
294
|
-
- **Uploads API
|
|
295
|
-
- **Data Kiosk API
|
|
222
|
+
- **Feeds API**: Upload data to Amazon (listings, prices, inventory, etc.)
|
|
223
|
+
- **Reports API**: Request and download reports (orders, inventory, fulfillment, etc.)
|
|
224
|
+
- **Uploads API**: Upload files for various SP-API operations
|
|
225
|
+
- **Data Kiosk API**: Access analytical data with GraphQL queries
|
|
296
226
|
|
|
297
227
|
```ruby
|
|
228
|
+
# Feeds API - create feed document, upload, submit
|
|
298
229
|
api = Peddler.feeds.new(aws_region, access_token)
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
# 2. Upload content to the document
|
|
303
|
-
# 3. Create feed referencing the document
|
|
304
|
-
# 4. Wait for feed to complete (e.g., SQS notification)
|
|
305
|
-
# 5. Get feed document (result feed document)
|
|
306
|
-
# 6. Download results to see processing outcome
|
|
307
|
-
|
|
308
|
-
# Step 1: Create feed document (input document)
|
|
309
|
-
document_response = api.create_feed_document(
|
|
310
|
-
contentType: "text/xml; charset=UTF-8"
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
# The `dig` method safely navigates the response hash
|
|
314
|
-
# If the response structure is:
|
|
315
|
-
# {
|
|
316
|
-
# "feedDocumentId": "amzn1.tortuga.3.abc123...",
|
|
317
|
-
# "url": "...",
|
|
318
|
-
# "encryptionDetails": {
|
|
319
|
-
# "standard": "AES",
|
|
320
|
-
# "key": "encryption-key",
|
|
321
|
-
# "initializationVector": "vector-value"
|
|
322
|
-
# }
|
|
323
|
-
# }
|
|
324
|
-
|
|
325
|
-
# Access top-level keys with dig
|
|
326
|
-
feed_document_id = document_response.dig("feedDocumentId")
|
|
327
|
-
upload_url = document_response.dig("url")
|
|
328
|
-
|
|
329
|
-
# Access nested keys - returns nil if any key in the path is missing
|
|
330
|
-
encryption_key = document_response.dig("encryptionDetails", "key")
|
|
331
|
-
|
|
332
|
-
# Step 2: Upload feed content to the input document
|
|
333
|
-
feed_content = File.read("inventory_update.xml")
|
|
334
|
-
api.upload_feed_document(upload_url, feed_content, "text/xml; charset=UTF-8")
|
|
335
|
-
|
|
336
|
-
# Step 3: Create feed referencing the input document
|
|
337
|
-
feed_response = api.create_feed(
|
|
338
|
-
feedType: "POST_INVENTORY_AVAILABILITY_DATA",
|
|
339
|
-
marketplaceIds: ["ATVPDKIKX0DER"],
|
|
340
|
-
inputFeedDocumentId: feed_document_id
|
|
341
|
-
)
|
|
342
|
-
feed_id = feed_response.dig("feedId")
|
|
343
|
-
|
|
344
|
-
# Step 4: Wait for feed to complete (polling or SQS notification)
|
|
345
|
-
# Poll until status is "DONE", "FATAL", or "CANCELLED"
|
|
346
|
-
loop do
|
|
347
|
-
feed_status = api.get_feed(feed_id)
|
|
348
|
-
status = feed_status.dig("processingStatus")
|
|
349
|
-
break if ["DONE", "FATAL", "CANCELLED"].include?(status)
|
|
350
|
-
sleep 30 # Wait 30 seconds before checking again
|
|
351
|
-
end
|
|
352
|
-
|
|
353
|
-
# Step 5: Get feed document (result document with processing results)
|
|
354
|
-
result_document_id = feed_status.dig("resultFeedDocumentId")
|
|
355
|
-
result_document = api.get_feed_document(result_document_id) if result_document_id
|
|
356
|
-
|
|
357
|
-
# Step 6: Download results to see processing outcome
|
|
358
|
-
if result_document
|
|
359
|
-
download_url = result_document.dig("url")
|
|
360
|
-
response = HTTP.get(download_url)
|
|
361
|
-
content = if result_document.dig("compressionAlgorithm") == "GZIP"
|
|
362
|
-
Zlib::GzipReader.new(response).read
|
|
363
|
-
else
|
|
364
|
-
response.to_s
|
|
365
|
-
end
|
|
366
|
-
# Parse content to check for errors/success
|
|
367
|
-
end
|
|
368
|
-
|
|
369
|
-
# JSON feed example
|
|
370
|
-
json_document = api.create_feed_document(
|
|
371
|
-
{ "contentType" => "application/json; charset=UTF-8" }
|
|
372
|
-
)
|
|
373
|
-
json_feed_content = JSON.generate({
|
|
374
|
-
"header": {
|
|
375
|
-
"sellerId": "SELLER_ID",
|
|
376
|
-
"version": "2.0",
|
|
377
|
-
"issueLocale": "en_US"
|
|
378
|
-
},
|
|
379
|
-
"messages": [
|
|
380
|
-
{
|
|
381
|
-
"messageId": 1,
|
|
382
|
-
"sku": "SKU123",
|
|
383
|
-
"operationType": "UPDATE",
|
|
384
|
-
"productType": "PRODUCT",
|
|
385
|
-
"attributes": {
|
|
386
|
-
# Your product attributes here
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
]
|
|
390
|
-
})
|
|
391
|
-
api.upload_feed_document(json_document.dig("url"), json_feed_content, "application/json; charset=UTF-8")
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
**Parsing Feed Results:**
|
|
395
|
-
|
|
396
|
-
After feed processing completes, parse the result document with type-safe data classes:
|
|
397
|
-
|
|
398
|
-
```ruby
|
|
399
|
-
# Get feed processing result document
|
|
400
|
-
result_document = api.get_feed_document(result_feed_document_id)
|
|
401
|
-
result_content = HTTP.get(result_document.dig("url")).to_s
|
|
402
|
-
|
|
403
|
-
# Handle compression if needed
|
|
404
|
-
if result_document.dig("compressionAlgorithm") == "GZIP"
|
|
405
|
-
require "zlib"
|
|
406
|
-
result_content = Zlib::GzipReader.new(StringIO.new(result_content)).read
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
# Parse with type safety
|
|
410
|
-
result_json = JSON.parse(result_content)
|
|
411
|
-
report = Peddler::Feeds::ListingsFeedProcessingReportSchema.parse(result_json)
|
|
412
|
-
|
|
413
|
-
# Access structured processing results
|
|
414
|
-
puts "Messages Processed: #{report.summary.messages_processed}"
|
|
415
|
-
puts "Messages Accepted: #{report.summary.messages_accepted}"
|
|
416
|
-
puts "Messages with Errors: #{report.summary.messages_with_error}"
|
|
417
|
-
puts "Messages with Warnings: #{report.summary.messages_with_warning}"
|
|
418
|
-
|
|
419
|
-
# Iterate through issues with type-safe access
|
|
420
|
-
report.issues.each do |issue|
|
|
421
|
-
puts "\nIssue in message #{issue.message_id}:"
|
|
422
|
-
puts " Severity: #{issue.severity}"
|
|
423
|
-
puts " Code: #{issue.code}"
|
|
424
|
-
puts " Message: #{issue.message}"
|
|
425
|
-
puts " SKU: #{issue.sku}" if issue.sku
|
|
426
|
-
end
|
|
230
|
+
document = api.create_feed_document(contentType: "text/xml; charset=UTF-8")
|
|
231
|
+
api.upload_feed_document(document.dig("url"), File.read("feed.xml"), "text/xml")
|
|
232
|
+
feed = api.create_feed(feedType: "POST_INVENTORY_AVAILABILITY_DATA", marketplaceIds: ["ATVPDKIKX0DER"], inputFeedDocumentId: document.dig("feedDocumentId"))
|
|
427
233
|
```
|
|
428
234
|
|
|
429
235
|
#### Data Kiosk API
|
|
430
236
|
|
|
431
|
-
The Data Kiosk API provides access to Amazon's analytical data through GraphQL queries. Peddler supports four Data Kiosk schema versions, each with type-safe
|
|
237
|
+
The Data Kiosk API provides access to Amazon's analytical data through GraphQL queries. Peddler supports four Data Kiosk schema versions, each with type-safe classes for parsing responses.
|
|
432
238
|
|
|
433
239
|
**Available Schemas:**
|
|
434
240
|
|
|
@@ -437,543 +243,50 @@ The Data Kiosk API provides access to Amazon's analytical data through GraphQL q
|
|
|
437
243
|
- **Economics20240315**: Economics and profitability data
|
|
438
244
|
- **VendorAnalytics20240930**: Vendor-specific analytics and forecasting data
|
|
439
245
|
|
|
440
|
-
**Basic Example:**
|
|
441
|
-
|
|
442
246
|
```ruby
|
|
443
247
|
api = Peddler.data_kiosk.new(aws_region, access_token)
|
|
444
|
-
|
|
445
|
-
# Create a Data Kiosk query request
|
|
446
|
-
response = api.create_query({
|
|
447
|
-
query: """
|
|
448
|
-
query {
|
|
449
|
-
salesAndTrafficByDate(
|
|
450
|
-
startDate: "2024-01-01",
|
|
451
|
-
endDate: "2024-01-31",
|
|
452
|
-
marketplaceIds: ["ATVPDKIKX0DER"]
|
|
453
|
-
) {
|
|
454
|
-
data {
|
|
455
|
-
date
|
|
456
|
-
orderItems
|
|
457
|
-
sales
|
|
458
|
-
pageViews
|
|
459
|
-
sessions
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
"""
|
|
464
|
-
})
|
|
465
|
-
|
|
466
|
-
# Get the query ID
|
|
248
|
+
response = api.create_query(query: "query { salesAndTrafficByDate(...) { data { date sales } } }")
|
|
467
249
|
query_id = response.dig("payload", "queryId")
|
|
468
|
-
|
|
469
|
-
# Poll for query completion
|
|
470
|
-
loop do
|
|
471
|
-
status = api.get_query(query_id)
|
|
472
|
-
processing_status = status.dig("payload", "processingStatus")
|
|
473
|
-
break if ["DONE", "FATAL"].include?(processing_status)
|
|
474
|
-
sleep 2
|
|
475
|
-
end
|
|
476
|
-
|
|
477
|
-
# Download the report document
|
|
478
|
-
result_document_id = status.dig("payload", "reportDocumentId")
|
|
479
|
-
document = api.get_report_document(result_document_id)
|
|
480
|
-
report_url = document.dig("url")
|
|
481
|
-
|
|
482
|
-
# Parse the response
|
|
483
|
-
require "net/http"
|
|
484
|
-
http_response = HTTP.get(report_url)
|
|
485
|
-
parsed_data = JSON.parse(http_response.to_s)
|
|
486
|
-
|
|
487
|
-
# Use type-safe parsing with Peddler's Structure classes
|
|
488
|
-
sales_data = Peddler::DataKiosk::SalesAndTraffic20231115.parse(parsed_data)
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
**Query Document Management:**
|
|
492
|
-
|
|
493
|
-
Peddler provides a helper method for downloading query documents:
|
|
494
|
-
|
|
495
|
-
```ruby
|
|
496
|
-
api = Peddler.data_kiosk.new(aws_region, access_token)
|
|
497
|
-
|
|
498
|
-
# Download a query document by ID (v2023-11-15 schemas)
|
|
499
|
-
document = api.download_query_document("amzn1.tortuga.3.abc123...")
|
|
500
|
-
|
|
501
|
-
# Or pass a full URL
|
|
502
|
-
document = api.download_query_document("https://...")
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
**Type-Safe Response Parsing:**
|
|
506
|
-
|
|
507
|
-
Each Data Kiosk schema version includes type-safe Structure classes that match the GraphQL response structure:
|
|
508
|
-
|
|
509
|
-
```ruby
|
|
510
|
-
# Parse economics data
|
|
511
|
-
response_data = JSON.parse(query_response_body)
|
|
512
|
-
analytics = Peddler::DataKiosk::Economics20240315.parse(response_data)
|
|
513
|
-
|
|
514
|
-
# Access typed attributes
|
|
515
|
-
analytics.analytics_economics_2024_03_15.each do |record|
|
|
516
|
-
puts "Sales: #{record.sales}"
|
|
517
|
-
puts "Fees: #{record.fees}"
|
|
518
|
-
puts "Net Proceeds: #{record.net_proceeds}"
|
|
519
|
-
puts "Date Range: #{record.start_date} to #{record.end_date}"
|
|
520
|
-
end
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
**Query Examples by Schema:**
|
|
524
|
-
|
|
525
|
-
```ruby
|
|
526
|
-
# Sales and Traffic by ASIN (2023-11-15)
|
|
527
|
-
query_sales_asin = """
|
|
528
|
-
query {
|
|
529
|
-
salesAndTrafficByAsin(
|
|
530
|
-
startDate: "2024-01-01",
|
|
531
|
-
endDate: "2024-01-31",
|
|
532
|
-
marketplaceIds: ["ATVPDKIKX0DER"]
|
|
533
|
-
) {
|
|
534
|
-
data {
|
|
535
|
-
startDate
|
|
536
|
-
endDate
|
|
537
|
-
parentAsin
|
|
538
|
-
childAsin
|
|
539
|
-
sku
|
|
540
|
-
sales {
|
|
541
|
-
orderedProductSales
|
|
542
|
-
totalOrderItems
|
|
543
|
-
unitsOrdered
|
|
544
|
-
}
|
|
545
|
-
traffic {
|
|
546
|
-
pageViews
|
|
547
|
-
pageViewsPercentage
|
|
548
|
-
sessions
|
|
549
|
-
sessionPercentage
|
|
550
|
-
unitSessionPercentage
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
"""
|
|
556
|
-
|
|
557
|
-
# Economics data (2024-03-15)
|
|
558
|
-
query_economics = """
|
|
559
|
-
query {
|
|
560
|
-
analytics {
|
|
561
|
-
economics {
|
|
562
|
-
data {
|
|
563
|
-
endDate
|
|
564
|
-
startDate
|
|
565
|
-
parentAsin
|
|
566
|
-
sales {
|
|
567
|
-
orderedProductSales
|
|
568
|
-
netProductSales
|
|
569
|
-
}
|
|
570
|
-
fees {
|
|
571
|
-
feeType
|
|
572
|
-
chargeAmount
|
|
573
|
-
}
|
|
574
|
-
netProceeds {
|
|
575
|
-
total
|
|
576
|
-
perUnit
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
"""
|
|
583
|
-
|
|
584
|
-
# Vendor analytics (2024-09-30)
|
|
585
|
-
query_vendor = """
|
|
586
|
-
query {
|
|
587
|
-
analytics {
|
|
588
|
-
vendoranalytics {
|
|
589
|
-
manufacturingView {
|
|
590
|
-
startDate
|
|
591
|
-
endDate
|
|
592
|
-
metrics {
|
|
593
|
-
costs
|
|
594
|
-
traffic
|
|
595
|
-
orders
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
"""
|
|
602
|
-
```
|
|
603
|
-
|
|
604
|
-
#### Communication and Customer Management APIs
|
|
605
|
-
|
|
606
|
-
- **Customer Feedback API (2024-06-01)**: Analyze customer reviews and returns data at item and browse node levels
|
|
607
|
-
- **Notifications API (v1)**: Subscribe to notifications for events like order updates
|
|
608
|
-
- **Messaging API (v1)**: Send messages to customers
|
|
609
|
-
- **Solicitations API (v1)**: Request customer reviews
|
|
610
|
-
|
|
611
|
-
```ruby
|
|
612
|
-
# Customer Feedback API example
|
|
613
|
-
api = Peddler.customer_feedback_2024_06_01.new(aws_region, access_token)
|
|
614
|
-
|
|
615
|
-
# Get item review topics (most positive and negative)
|
|
616
|
-
review_topics = api.get_item_review_topics(
|
|
617
|
-
"B08N5WRWNW", # ASIN
|
|
618
|
-
Marketplace.id("US"),
|
|
619
|
-
"frequency" # Sort by frequency
|
|
620
|
-
)
|
|
621
|
-
|
|
622
|
-
# Get item review trends for past 6 months
|
|
623
|
-
review_trends = api.get_item_review_trends(
|
|
624
|
-
"B08N5WRWNW",
|
|
625
|
-
Marketplace.id("US")
|
|
626
|
-
)
|
|
627
|
-
|
|
628
|
-
# Get browse node return topics
|
|
629
|
-
return_topics = api.get_browse_node_return_topics(
|
|
630
|
-
"123456789", # Browse node ID
|
|
631
|
-
Marketplace.id("US")
|
|
632
|
-
)
|
|
633
|
-
```
|
|
634
|
-
|
|
635
|
-
```ruby
|
|
636
|
-
api = Peddler.notifications.new(aws_region, access_token)
|
|
637
|
-
# Create destination
|
|
638
|
-
destination = api.create_destination(
|
|
639
|
-
name: "MyEventQueue",
|
|
640
|
-
resourceSpecification: {
|
|
641
|
-
sqs: { arn: "arn:aws:sqs:us-east-1:123456789012:MyQueue" }
|
|
642
|
-
}
|
|
643
|
-
)
|
|
644
|
-
destination_id = destination.dig("payload", "destinationId")
|
|
645
|
-
|
|
646
|
-
# Create subscription
|
|
647
|
-
api.create_subscription(
|
|
648
|
-
notificationType: "ANY_OFFER_CHANGED",
|
|
649
|
-
destinationId: destination_id,
|
|
650
|
-
payloadVersion: "1"
|
|
651
|
-
)
|
|
652
|
-
|
|
653
|
-
# For sandbox testing (requires grantless token)
|
|
654
|
-
sandbox_api = Peddler.notifications.new(aws_region, grantless_access_token)
|
|
655
|
-
sandbox_api = sandbox_api.sandbox
|
|
656
|
-
# Get all destinations
|
|
657
|
-
destinations = sandbox_api.get_destinations
|
|
658
|
-
|
|
659
|
-
# Get specific subscription
|
|
660
|
-
subscription = sandbox_api.get_subscription("LISTINGS_ITEM_ISSUES_CHANGE")
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
**Parsing Notifications:**
|
|
664
|
-
|
|
665
|
-
Once you receive notifications (via SQS or EventBridge), parse them with type-safe data classes:
|
|
666
|
-
|
|
667
|
-
```ruby
|
|
668
|
-
# Parse notification from SQS message
|
|
669
|
-
notification_json = JSON.parse(sqs_message.body)
|
|
670
|
-
notification = Peddler::Notifications::AnyOfferChanged.parse(notification_json)
|
|
671
|
-
|
|
672
|
-
# Type-safe access to notification data
|
|
673
|
-
notification.notification_version # => "1.0"
|
|
674
|
-
notification.notification_type # => "ANY_OFFER_CHANGED"
|
|
675
|
-
|
|
676
|
-
# Access payload with autocomplete
|
|
677
|
-
notification.payload.offers.each do |offer|
|
|
678
|
-
puts "Seller: #{offer.seller_id}"
|
|
679
|
-
puts "Price: #{offer.listing_price.amount} #{offer.listing_price.currency_code}"
|
|
680
|
-
puts "Condition: #{offer.item_condition}"
|
|
681
|
-
puts "Prime: #{offer.is_prime?}" if offer.respond_to?(:is_prime?)
|
|
682
|
-
end
|
|
250
|
+
# Poll for completion and download document
|
|
683
251
|
```
|
|
684
|
-
|
|
685
252
|
#### Vendor APIs
|
|
686
253
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
- **Vendor
|
|
690
|
-
- **Vendor Direct Fulfillment
|
|
691
|
-
- **Vendor Direct Fulfillment
|
|
692
|
-
- **Vendor Direct Fulfillment
|
|
693
|
-
- **Vendor Direct Fulfillment
|
|
694
|
-
- **Vendor
|
|
695
|
-
- **Vendor
|
|
696
|
-
- **Vendor
|
|
697
|
-
- **Vendor Invoices API (v1)**: Submit and track invoices
|
|
698
|
-
- **Vendor Transaction Status API (v1)**: Check transaction status
|
|
254
|
+
- **Vendor Orders API**: Retrieve purchase orders
|
|
255
|
+
- **Vendor Direct Fulfillment Orders API**: Manage direct fulfillment orders
|
|
256
|
+
- **Vendor Direct Fulfillment Shipping API**: Manage shipping for direct fulfillment
|
|
257
|
+
- **Vendor Direct Fulfillment Payments API**: Process payments for direct fulfillment
|
|
258
|
+
- **Vendor Direct Fulfillment Inventory API**: Manage inventory for direct fulfillment
|
|
259
|
+
- **Vendor Direct Fulfillment Transactions API**: Track transaction status
|
|
260
|
+
- **Vendor Direct Fulfillment Sandbox Test Data API**: Generate test data in sandbox
|
|
261
|
+
- **Vendor Shipments API**: Track vendor shipments
|
|
262
|
+
- **Vendor Invoices API**: Submit and track invoices
|
|
263
|
+
- **Vendor Transaction Status API**: Check transaction status
|
|
699
264
|
|
|
700
265
|
```ruby
|
|
701
266
|
api = Peddler.vendor_orders.new(aws_region, access_token)
|
|
702
|
-
orders = api.get_purchase_orders(
|
|
703
|
-
limit: 10,
|
|
704
|
-
createdAfter: "2023-01-01T00:00:00Z"
|
|
705
|
-
).parse
|
|
267
|
+
orders = api.get_purchase_orders(limit: 10, createdAfter: "2023-01-01T00:00:00Z").parse
|
|
706
268
|
```
|
|
707
269
|
|
|
708
270
|
#### Authorization and Account Management APIs
|
|
709
271
|
|
|
710
|
-
- **Application Management API
|
|
711
|
-
- **Tokens API
|
|
712
|
-
- **Sellers API
|
|
713
|
-
- **Services API
|
|
714
|
-
- **Seller Wallet API
|
|
715
|
-
- **Application Integrations API
|
|
716
|
-
- **Vehicles API
|
|
717
|
-
|
|
718
|
-
### Additional API Examples
|
|
719
|
-
|
|
720
|
-
#### Product Pricing API
|
|
721
|
-
|
|
722
|
-
```ruby
|
|
723
|
-
# Using Product Pricing v0
|
|
724
|
-
api = Peddler.product_pricing_v0.new(aws_region, access_token)
|
|
725
|
-
|
|
726
|
-
# Get pricing information for an ASIN
|
|
727
|
-
pricing = api.get_pricing(
|
|
728
|
-
Marketplace.id("US"),
|
|
729
|
-
"Asin",
|
|
730
|
-
asins: ["B08N5WRWNW"]
|
|
731
|
-
)
|
|
732
|
-
|
|
733
|
-
# Get competitive pricing for an ASIN
|
|
734
|
-
competitive = api.get_competitive_pricing(
|
|
735
|
-
Marketplace.id("US"),
|
|
736
|
-
"Asin",
|
|
737
|
-
asins: ["B08N5WRWNW"]
|
|
738
|
-
)
|
|
739
|
-
|
|
740
|
-
# Get offers for a specific item
|
|
741
|
-
offers = api.get_item_offers(
|
|
742
|
-
Marketplace.id("US"),
|
|
743
|
-
"New",
|
|
744
|
-
"B08N5WRWNW"
|
|
745
|
-
)
|
|
746
|
-
|
|
747
|
-
# Batch request for multiple items (2022-05-01 API)
|
|
748
|
-
api = Peddler.product_pricing_2022_05_01.new(aws_region, access_token)
|
|
749
|
-
batch_request = {
|
|
750
|
-
requests: [
|
|
751
|
-
{
|
|
752
|
-
uri: "/products/pricing/2022-05-01/items/competitiveSummary",
|
|
753
|
-
method: "GET",
|
|
754
|
-
asin: "B08N5WRWNW",
|
|
755
|
-
marketplaceId: Marketplace.id("US"),
|
|
756
|
-
includedData: ["featuredBuyingOptions", "referencePrices", "lowestPricedOffers"]
|
|
757
|
-
},
|
|
758
|
-
# Additional items...
|
|
759
|
-
]
|
|
760
|
-
}
|
|
761
|
-
results = api.get_competitive_summary(batch_request)
|
|
762
|
-
```
|
|
763
|
-
|
|
764
|
-
#### Listings Items API
|
|
765
|
-
|
|
766
|
-
```ruby
|
|
767
|
-
api = Peddler.listings_items.new(aws_region, access_token)
|
|
768
|
-
|
|
769
|
-
# Create or update a listing
|
|
770
|
-
listing_result = api.put_listings_item(
|
|
771
|
-
"SELLER_ID",
|
|
772
|
-
"SKU123",
|
|
773
|
-
Marketplace.id("US"),
|
|
774
|
-
{
|
|
775
|
-
productType: "PRODUCT",
|
|
776
|
-
requirements: "LISTING_OFFER_ONLY",
|
|
777
|
-
attributes: {
|
|
778
|
-
merchant_suggested_asin: [{
|
|
779
|
-
value: "B08N5WRWNW",
|
|
780
|
-
marketplace_id: Marketplace.id("US")
|
|
781
|
-
}],
|
|
782
|
-
condition_type: [{
|
|
783
|
-
value: "new_new",
|
|
784
|
-
marketplace_id: Marketplace.id("US")
|
|
785
|
-
}],
|
|
786
|
-
# Additional attributes...
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
)
|
|
790
|
-
|
|
791
|
-
# Update specific listing elements with JSON Patch
|
|
792
|
-
patch_result = api.patch_listings_item(
|
|
793
|
-
"SELLER_ID",
|
|
794
|
-
"SKU123",
|
|
795
|
-
Marketplace.id("US"),
|
|
796
|
-
{
|
|
797
|
-
productType: "PRODUCT",
|
|
798
|
-
patches: [
|
|
799
|
-
{
|
|
800
|
-
op: "replace",
|
|
801
|
-
path: "/attributes/purchasable_offer",
|
|
802
|
-
value: [{
|
|
803
|
-
currency: "USD",
|
|
804
|
-
our_price: [{
|
|
805
|
-
schedule: [{
|
|
806
|
-
value_with_tax: 39.99
|
|
807
|
-
}]
|
|
808
|
-
}]
|
|
809
|
-
}]
|
|
810
|
-
}
|
|
811
|
-
]
|
|
812
|
-
}
|
|
813
|
-
)
|
|
814
|
-
|
|
815
|
-
# Get listing details
|
|
816
|
-
listing = api.get_listings_item(
|
|
817
|
-
"SELLER_ID",
|
|
818
|
-
"SKU123",
|
|
819
|
-
Marketplace.id("US"),
|
|
820
|
-
included_data: "attributes,issues"
|
|
821
|
-
)
|
|
822
|
-
|
|
823
|
-
# Delete a listing
|
|
824
|
-
api.delete_listings_item("SELLER_ID", "SKU123", Marketplace.id("US"))
|
|
825
|
-
```
|
|
826
|
-
|
|
827
|
-
#### Listings Restrictions API
|
|
272
|
+
- **Application Management API**: Manage application authorization
|
|
273
|
+
- **Tokens API**: Generate restricted data tokens for accessing PII
|
|
274
|
+
- **Sellers API**: Get seller account information and marketplace participation
|
|
275
|
+
- **Services API**: Manage seller services and subscriptions
|
|
276
|
+
- **Seller Wallet API**: Manage seller financial accounts
|
|
277
|
+
- **Application Integrations API**: Manage app integrations
|
|
278
|
+
- **Vehicles API**: Manage vehicle data for automotive products
|
|
828
279
|
|
|
829
|
-
|
|
830
|
-
api = Peddler.listings_restrictions.new(aws_region, access_token)
|
|
831
|
-
|
|
832
|
-
# Check restrictions for an ASIN
|
|
833
|
-
restrictions = api.get_listings_restrictions(
|
|
834
|
-
"B08N5WRWNW",
|
|
835
|
-
"SELLER_ID",
|
|
836
|
-
Marketplace.id("US"),
|
|
837
|
-
condition_type: "new_new"
|
|
838
|
-
)
|
|
839
|
-
```
|
|
840
|
-
|
|
841
|
-
#### Product Type Definitions API
|
|
842
|
-
|
|
843
|
-
```ruby
|
|
844
|
-
api = Peddler.product_type_definitions.new(aws_region, access_token)
|
|
845
|
-
|
|
846
|
-
# Get schema for a product type
|
|
847
|
-
definition = api.get_definitions_product_type(
|
|
848
|
-
"PRODUCT",
|
|
849
|
-
Marketplace.id("US"),
|
|
850
|
-
requirements: "LISTING_OFFER_ONLY"
|
|
851
|
-
)
|
|
852
|
-
|
|
853
|
-
# Download the JSON schema
|
|
854
|
-
schema_url = definition.dig("schema", "link", "resource")
|
|
855
|
-
json_schema = HTTP.get(schema_url).parse(:json)
|
|
856
|
-
```
|
|
857
|
-
|
|
858
|
-
#### Reports API
|
|
859
|
-
|
|
860
|
-
```ruby
|
|
861
|
-
api = Peddler.reports.new(aws_region, access_token)
|
|
862
|
-
|
|
863
|
-
# Request a report
|
|
864
|
-
report_response = api.create_report({
|
|
865
|
-
"reportType" => "GET_MERCHANTS_LISTINGS_FYP_REPORT",
|
|
866
|
-
"marketplaceIds" => Marketplace.ids("US")
|
|
867
|
-
})
|
|
868
|
-
report_id = report_response.dig("reportId")
|
|
869
|
-
|
|
870
|
-
# Get report status
|
|
871
|
-
report = api.get_report(report_id)
|
|
872
|
-
|
|
873
|
-
# Get all reports of a specific type
|
|
874
|
-
reports = api.get_reports(report_types: ["GET_MERCHANTS_LISTINGS_FYP_REPORT"])
|
|
875
|
-
|
|
876
|
-
# Download a report document (using convenience helper)
|
|
877
|
-
response = api.download_report_document("DOCUMENT_ID")
|
|
878
|
-
# Process the downloaded report content from response.body...
|
|
879
|
-
```
|
|
880
|
-
|
|
881
|
-
#### Understanding Report Types
|
|
882
|
-
|
|
883
|
-
SP-API provides two different types of reports with different formats and APIs:
|
|
280
|
+
### Complex Workflows
|
|
884
281
|
|
|
885
|
-
|
|
282
|
+
Detailed workflows are available in test files with VCR cassettes:
|
|
886
283
|
|
|
887
|
-
|
|
284
|
+
- **Feeds API**: [test/peddler/apis/feeds_2021_06_30_test.rb](test/peddler/apis/feeds_2021_06_30_test.rb)
|
|
285
|
+
- **Data Kiosk API**: [test/peddler/apis/data_kiosk_2023_11_15_test.rb](test/peddler/apis/data_kiosk_2023_11_15_test.rb)
|
|
286
|
+
- **Reports API**: [lib/peddler/apis/reports_2021_06_30.rb](lib/peddler/apis/reports_2021_06_30.rb) (YARD docs)
|
|
287
|
+
- **Notifications API**: [lib/peddler/notifications/](lib/peddler/notifications/) (type-safe parsing)
|
|
888
288
|
|
|
889
|
-
|
|
890
|
-
- Vendor Real-Time Inventory Report
|
|
891
|
-
- Seller Sales and Traffic Report
|
|
892
|
-
- Account Health Report
|
|
893
|
-
- Vendor Forecasting Report
|
|
894
|
-
- Customer Feedback Reports
|
|
895
|
-
|
|
896
|
-
Location in Peddler: `lib/peddler/reports/` with generated Structure-based classes
|
|
897
|
-
|
|
898
|
-
```ruby
|
|
899
|
-
# Example: Request and parse a vendor real-time inventory report
|
|
900
|
-
api = Peddler.reports.new(aws_region, access_token)
|
|
901
|
-
|
|
902
|
-
# Create report request
|
|
903
|
-
report_response = api.create_report({
|
|
904
|
-
"reportType" => "GET_VENDOR_REAL_TIME_INVENTORY_REPORT",
|
|
905
|
-
"marketplaceIds" => [Marketplace.id("US")],
|
|
906
|
-
"reportOptions" => {
|
|
907
|
-
"reportPeriod" => "WEEK",
|
|
908
|
-
"distributorView" => "MANUFACTURING",
|
|
909
|
-
"sellingProgram" => "RETAIL",
|
|
910
|
-
"startDate" => "2024-01-01",
|
|
911
|
-
"endDate" => "2024-01-07"
|
|
912
|
-
}
|
|
913
|
-
})
|
|
914
|
-
|
|
915
|
-
# Wait for report to be ready, then download
|
|
916
|
-
report_id = report_response.dig("reportId")
|
|
917
|
-
# ... check status until DONE ...
|
|
918
|
-
document_id = api.get_report(report_id).dig("reportDocumentId")
|
|
919
|
-
|
|
920
|
-
# Download and parse JSON report
|
|
921
|
-
document = api.get_report_document(document_id)
|
|
922
|
-
report_json = HTTP.get(document.dig("url")).parse(:json)
|
|
923
|
-
|
|
924
|
-
# Use typed data classes
|
|
925
|
-
report = Peddler::Reports::VendorRealTimeInventory::Report.new(report_json)
|
|
926
|
-
report.report_data.each do |data|
|
|
927
|
-
puts "ASIN: #{data.asin}, Inventory: #{data.highly_available_inventory}"
|
|
928
|
-
end
|
|
929
|
-
```
|
|
930
|
-
|
|
931
|
-
**2. Legacy Flat-File Reports** (Tab-Delimited)
|
|
932
|
-
|
|
933
|
-
These are older reports that return tab-delimited text files (TSV format), often GZIP compressed. These require manual CSV parsing and do NOT have Structure-based data classes.
|
|
934
|
-
|
|
935
|
-
Examples:
|
|
936
|
-
- `GET_MERCHANT_LISTINGS_ALL_DATA`
|
|
937
|
-
- `GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA`
|
|
938
|
-
- `GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE_GENERAL`
|
|
939
|
-
|
|
940
|
-
These must be parsed manually using Ruby's CSV library:
|
|
941
|
-
|
|
942
|
-
```ruby
|
|
943
|
-
# Download flat-file report
|
|
944
|
-
document = api.get_report_document(document_id)
|
|
945
|
-
response = HTTP.get(document.dig("url"))
|
|
946
|
-
|
|
947
|
-
# Handle GZIP compression if needed
|
|
948
|
-
body = if document.dig("compressionAlgorithm") == "GZIP"
|
|
949
|
-
Zlib::GzipReader.new(StringIO.new(response.body.to_s)).read
|
|
950
|
-
else
|
|
951
|
-
response.body.to_s
|
|
952
|
-
end
|
|
953
|
-
|
|
954
|
-
# Parse tab-delimited data
|
|
955
|
-
csv_options = {
|
|
956
|
-
col_sep: "\t",
|
|
957
|
-
headers: true,
|
|
958
|
-
quote_char: "\x00",
|
|
959
|
-
encoding: "UTF-8"
|
|
960
|
-
}
|
|
961
|
-
CSV.parse(body, **csv_options) do |row|
|
|
962
|
-
# Process each row as a hash
|
|
963
|
-
puts "SKU: #{row['sku']}, ASIN: #{row['asin']}, Quantity: #{row['quantity']}"
|
|
964
|
-
end
|
|
965
|
-
```
|
|
966
|
-
|
|
967
|
-
For a complete list of report types and their formats, see the [Report Type Values documentation](https://developer-docs.amazon.com/sp-api/docs/report-type-values).
|
|
968
|
-
|
|
969
|
-
#### Sellers API
|
|
970
|
-
|
|
971
|
-
```ruby
|
|
972
|
-
api = Peddler.sellers.new(aws_region, access_token)
|
|
973
|
-
|
|
974
|
-
# Get marketplace participations
|
|
975
|
-
participations = api.get_marketplace_participations
|
|
976
|
-
```
|
|
289
|
+
For complete method signatures, see [sig/peddler/apis/](sig/peddler/apis/)
|
|
977
290
|
|
|
978
291
|
For a complete list of available APIs and their detailed documentation, refer to the [API models repository][swagger-models].
|
|
979
292
|
|
|
@@ -12,7 +12,7 @@ module Peddler
|
|
|
12
12
|
# report would contain data for each complete hour within the time span.
|
|
13
13
|
Report = Structure.new do
|
|
14
14
|
# @return [Array<reportData>] List of hour and ASIN combinations.
|
|
15
|
-
attribute(:report_data,
|
|
15
|
+
attribute(:report_data, [ReportData], from: "reportData")
|
|
16
16
|
|
|
17
17
|
# @return [Hash] Summarizes the original report request.
|
|
18
18
|
attribute(:report_specification, ReportSpecification, from: "reportSpecification")
|
data/lib/peddler/version.rb
CHANGED
|
@@ -2,20 +2,20 @@ module Peddler
|
|
|
2
2
|
module Reports
|
|
3
3
|
module VendorRealTimeSales
|
|
4
4
|
class Report < Data
|
|
5
|
-
def self.new: (report_data: Array[
|
|
6
|
-
| (Array[
|
|
7
|
-
def self.[]: (report_data: Array[
|
|
8
|
-
| (Array[
|
|
5
|
+
def self.new: (report_data: Array[Peddler::Reports::VendorRealTimeSales::ReportData]?, report_specification: Peddler::Reports::VendorRealTimeSales::ReportSpecification?) -> Peddler::Reports::VendorRealTimeSales::Report
|
|
6
|
+
| (Array[Peddler::Reports::VendorRealTimeSales::ReportData]?, Peddler::Reports::VendorRealTimeSales::ReportSpecification?) -> Peddler::Reports::VendorRealTimeSales::Report
|
|
7
|
+
def self.[]: (report_data: Array[Peddler::Reports::VendorRealTimeSales::ReportData]?, report_specification: Peddler::Reports::VendorRealTimeSales::ReportSpecification?) -> Peddler::Reports::VendorRealTimeSales::Report
|
|
8
|
+
| (Array[Peddler::Reports::VendorRealTimeSales::ReportData]?, Peddler::Reports::VendorRealTimeSales::ReportSpecification?) -> Peddler::Reports::VendorRealTimeSales::Report
|
|
9
9
|
|
|
10
10
|
def self.members: () -> [ :report_data, :report_specification ]
|
|
11
11
|
|
|
12
12
|
def self.parse: (?Hash[String | Symbol, untyped], **untyped) -> Peddler::Reports::VendorRealTimeSales::Report
|
|
13
13
|
|
|
14
|
-
attr_reader report_data: Array[
|
|
14
|
+
attr_reader report_data: Array[Peddler::Reports::VendorRealTimeSales::ReportData]?
|
|
15
15
|
attr_reader report_specification: Peddler::Reports::VendorRealTimeSales::ReportSpecification?
|
|
16
16
|
|
|
17
17
|
def members: () -> [ :report_data, :report_specification ]
|
|
18
|
-
def to_h: () -> { report_data: Array[
|
|
18
|
+
def to_h: () -> { report_data: Array[Peddler::Reports::VendorRealTimeSales::ReportData]?, report_specification: Peddler::Reports::VendorRealTimeSales::ReportSpecification? }
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
class ReportData < Data
|