cardmagic-etsy 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +13 -0
- data/Gemfile +11 -0
- data/LICENSE +9 -0
- data/README.md +348 -0
- data/Rakefile +12 -0
- data/etsy.gemspec +34 -0
- data/lib/etsy.rb +223 -0
- data/lib/etsy/about.rb +15 -0
- data/lib/etsy/address.rb +47 -0
- data/lib/etsy/attribute_value.rb +46 -0
- data/lib/etsy/basic_client.rb +32 -0
- data/lib/etsy/category.rb +84 -0
- data/lib/etsy/country.rb +27 -0
- data/lib/etsy/favorite_listing.rb +26 -0
- data/lib/etsy/image.rb +44 -0
- data/lib/etsy/listing.rb +296 -0
- data/lib/etsy/model.rb +127 -0
- data/lib/etsy/payment_template.rb +33 -0
- data/lib/etsy/profile.rb +49 -0
- data/lib/etsy/receipt.rb +37 -0
- data/lib/etsy/request.rb +150 -0
- data/lib/etsy/response.rb +128 -0
- data/lib/etsy/section.rb +16 -0
- data/lib/etsy/secure_client.rb +131 -0
- data/lib/etsy/shipping_info.rb +27 -0
- data/lib/etsy/shipping_template.rb +41 -0
- data/lib/etsy/shop.rb +88 -0
- data/lib/etsy/transaction.rb +29 -0
- data/lib/etsy/user.rb +109 -0
- data/lib/etsy/variation/property_set.rb +71 -0
- data/lib/etsy/verification_request.rb +17 -0
- data/lib/etsy/version.rb +3 -0
- data/test/fixtures/about/getAbout.json +16 -0
- data/test/fixtures/address/getUserAddresses.json +12 -0
- data/test/fixtures/attribute_value/findAllListingPropertyValues.json +44 -0
- data/test/fixtures/category/findAllSubCategoryChildren.json +78 -0
- data/test/fixtures/category/findAllTopCategory.json +347 -0
- data/test/fixtures/category/findAllTopCategory.single.json +18 -0
- data/test/fixtures/category/findAllTopCategoryChildren.json +308 -0
- data/test/fixtures/category/getCategory.multiple.json +28 -0
- data/test/fixtures/category/getCategory.single.json +18 -0
- data/test/fixtures/country/getCountry.json +1 -0
- data/test/fixtures/favorite_listing/findAllFavoriteListings.json +1 -0
- data/test/fixtures/image/findAllListingImages.json +102 -0
- data/test/fixtures/listing/findAllListingActive.category.json +827 -0
- data/test/fixtures/listing/findAllShopListings.json +69 -0
- data/test/fixtures/listing/getListing.multiple.json +1 -0
- data/test/fixtures/listing/getListing.single.includeImages.json +1 -0
- data/test/fixtures/listing/getListing.single.json +1 -0
- data/test/fixtures/payment_template/getPaymentTemplate.json +1 -0
- data/test/fixtures/profile/new.json +28 -0
- data/test/fixtures/receipt/findAllShopReceipts.json +28 -0
- data/test/fixtures/section/getShopSection.json +18 -0
- data/test/fixtures/shipping_info/getShippingInfo.json +1 -0
- data/test/fixtures/shipping_template/getShippingTemplate.json +1 -0
- data/test/fixtures/shop/findAllShop.json +1 -0
- data/test/fixtures/shop/findAllShop.single.json +1 -0
- data/test/fixtures/shop/getShop.multiple.json +1 -0
- data/test/fixtures/shop/getShop.single.json +34 -0
- data/test/fixtures/transaction/findAllShopTransactions.json +1 -0
- data/test/fixtures/user/getUser.multiple.json +29 -0
- data/test/fixtures/user/getUser.single.json +13 -0
- data/test/fixtures/user/getUser.single.private.json +18 -0
- data/test/fixtures/user/getUser.single.withProfile.json +38 -0
- data/test/fixtures/user/getUser.single.withShops.json +41 -0
- data/test/test_helper.rb +45 -0
- data/test/unit/etsy/address_test.rb +61 -0
- data/test/unit/etsy/attribute_value_test.rb +67 -0
- data/test/unit/etsy/basic_client_test.rb +30 -0
- data/test/unit/etsy/category_test.rb +106 -0
- data/test/unit/etsy/country_test.rb +64 -0
- data/test/unit/etsy/favorite_listing_test.rb +44 -0
- data/test/unit/etsy/image_test.rb +51 -0
- data/test/unit/etsy/listing_test.rb +268 -0
- data/test/unit/etsy/model_test.rb +64 -0
- data/test/unit/etsy/payment_template_test.rb +68 -0
- data/test/unit/etsy/profile_test.rb +111 -0
- data/test/unit/etsy/receipt_test.rb +107 -0
- data/test/unit/etsy/request_test.rb +190 -0
- data/test/unit/etsy/response_test.rb +175 -0
- data/test/unit/etsy/section_test.rb +28 -0
- data/test/unit/etsy/secure_client_test.rb +132 -0
- data/test/unit/etsy/shipping_info_test.rb +24 -0
- data/test/unit/etsy/shipping_template_test.rb +24 -0
- data/test/unit/etsy/shop_about_test.rb +43 -0
- data/test/unit/etsy/shop_test.rb +116 -0
- data/test/unit/etsy/transaction_test.rb +61 -0
- data/test/unit/etsy/user_test.rb +250 -0
- data/test/unit/etsy/verification_request_test.rb +26 -0
- data/test/unit/etsy_test.rb +173 -0
- metadata +293 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
module Etsy
|
2
|
+
class ShippingInfo
|
3
|
+
include Etsy::Model
|
4
|
+
|
5
|
+
attribute :id, :from => :shipping_info_id
|
6
|
+
|
7
|
+
attributes :origin_country_id, :destination_country_id, :currency_code, :primary_cost, :secondary_cost, :listing_id, :region_id, :origin_country_name, :destination_country_name
|
8
|
+
|
9
|
+
def self.find(id, credentials = {})
|
10
|
+
options = {
|
11
|
+
:access_token => credentials[:access_token],
|
12
|
+
:access_secret => credentials[:access_secret],
|
13
|
+
:require_secure => true
|
14
|
+
}
|
15
|
+
get("/shipping/info/#{id}", options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.find_by_listing_id(listing_id, credentials = {})
|
19
|
+
options = {
|
20
|
+
:access_token => credentials[:access_token],
|
21
|
+
:access_secret => credentials[:access_secret],
|
22
|
+
:require_secure => true
|
23
|
+
}
|
24
|
+
get("/listings/#{listing_id}/shipping/info", options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Etsy
|
2
|
+
class ShippingTemplate
|
3
|
+
include Etsy::Model
|
4
|
+
|
5
|
+
attribute :id, :from => :shipping_template_id
|
6
|
+
|
7
|
+
attributes :title, :user_id
|
8
|
+
|
9
|
+
def self.create(options = {})
|
10
|
+
options.merge!(:require_secure => true)
|
11
|
+
post("/shipping/templates", options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.find(id, credentials = {})
|
15
|
+
options = {
|
16
|
+
:access_token => credentials[:access_token],
|
17
|
+
:access_secret => credentials[:access_secret],
|
18
|
+
:require_secure => true
|
19
|
+
}
|
20
|
+
get("/shipping/templates/#{id}", options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.find_entries(id, credentials = {})
|
24
|
+
options = {
|
25
|
+
:access_token => credentials[:access_token],
|
26
|
+
:access_secret => credentials[:access_secret],
|
27
|
+
:require_secure => true
|
28
|
+
}
|
29
|
+
get("/shipping/templates/#{id}/entries", options)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.find_by_user(user, credentials = {})
|
33
|
+
options = {
|
34
|
+
:access_token => credentials[:access_token],
|
35
|
+
:access_secret => credentials[:access_secret],
|
36
|
+
:require_secure => true
|
37
|
+
}
|
38
|
+
get("/users/#{user.id}/shipping/templates", options)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/etsy/shop.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = Shop
|
4
|
+
#
|
5
|
+
# Represents a single Etsy shop. Users may or may not have an associated shop.
|
6
|
+
#
|
7
|
+
# A shop has the following attributes:
|
8
|
+
#
|
9
|
+
# [name] The shop's name
|
10
|
+
# [title] A brief heading for the shop's main page
|
11
|
+
# [announcement] An announcement to buyers (displays on the shop's home page)
|
12
|
+
# [message] The message sent to users who buy from this shop
|
13
|
+
# [image_url] The full URL to the shops's banner image
|
14
|
+
# [active_listings_count] The number of active listings present in this shop
|
15
|
+
# [url] The full URL to the shop on Etsy
|
16
|
+
# [favorers_count] Number of favorers
|
17
|
+
|
18
|
+
class Shop
|
19
|
+
|
20
|
+
include Etsy::Model
|
21
|
+
|
22
|
+
attributes :title, :announcement, :user_id
|
23
|
+
|
24
|
+
attribute :id, :from => :shop_id
|
25
|
+
attribute :image_url, :from => 'image_url_760x100'
|
26
|
+
attribute :active_listings_count, :from => 'listing_active_count'
|
27
|
+
attribute :updated, :from => :last_updated_tsz
|
28
|
+
attribute :created, :from => :creation_tsz
|
29
|
+
attribute :name, :from => :shop_name
|
30
|
+
attribute :message, :from => :sale_message
|
31
|
+
attribute :url, :from => :url
|
32
|
+
attribute :favorers_count, :from => :num_favorers
|
33
|
+
attribute :icon_url, :from => 'icon_url_fullxfull'
|
34
|
+
|
35
|
+
# Retrieve one or more shops by name or ID:
|
36
|
+
#
|
37
|
+
# Etsy::Shop.find('reagent')
|
38
|
+
#
|
39
|
+
# You can find multiple shops by passing an array of identifiers:
|
40
|
+
#
|
41
|
+
# Etsy::Shop.find(['reagent', 'littletjane'])
|
42
|
+
#
|
43
|
+
def self.find(*identifiers_and_options)
|
44
|
+
self.find_one_or_more('shops', identifiers_and_options)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Retrieve a list of all shops. By default it fetches 25 at a time, but that can
|
48
|
+
# be configured by passing the :limit and :offset parameters:
|
49
|
+
#
|
50
|
+
# Etsy::Shop.all(:limit => 100, :offset => 100)
|
51
|
+
#
|
52
|
+
def self.all(options = {})
|
53
|
+
self.get_all("/shops", options)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Time that this shop was created
|
57
|
+
#
|
58
|
+
def created_at
|
59
|
+
Time.at(created)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Time that this shop was last updated
|
63
|
+
#
|
64
|
+
def updated_at
|
65
|
+
Time.at(updated)
|
66
|
+
end
|
67
|
+
|
68
|
+
# The collection of listings associated with this shop
|
69
|
+
#
|
70
|
+
def listings(state = nil, options = {})
|
71
|
+
state = state ? {:state => state} : {}
|
72
|
+
Listing.find_all_by_shop_id(id, state.merge(options).merge(oauth))
|
73
|
+
end
|
74
|
+
|
75
|
+
def sections
|
76
|
+
Section.find_by_shop(self)
|
77
|
+
end
|
78
|
+
|
79
|
+
def about
|
80
|
+
About.find_by_shop(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def oauth
|
85
|
+
oauth = (token && secret) ? {:access_token => token, :access_secret => secret} : {}
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Etsy
|
2
|
+
class Transaction
|
3
|
+
include Model
|
4
|
+
|
5
|
+
attribute :id, :from => :transaction_id
|
6
|
+
attribute :buyer_id, :from => :buyer_user_id
|
7
|
+
attributes :quantity, :listing_id
|
8
|
+
|
9
|
+
def self.find_all_by_shop_id(shop_id, options = {})
|
10
|
+
get_all("/shops/#{shop_id}/transactions", options)
|
11
|
+
end
|
12
|
+
|
13
|
+
#Find all Transactions by the buyer_id
|
14
|
+
#
|
15
|
+
def self.find_all_by_buyer_id(user_id, options = {})
|
16
|
+
get_all("/users/#{user_id}/transactions", options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.find_all_by_receipt_id(receipt_id, options = {})
|
20
|
+
get_all("/receipts/#{receipt_id}/transactions", options)
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def buyer
|
25
|
+
@buyer ||= User.find(buyer_id)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
data/lib/etsy/user.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
module Etsy
|
2
|
+
|
3
|
+
# = User
|
4
|
+
#
|
5
|
+
# Represents a single Etsy user - has the following attributes:
|
6
|
+
#
|
7
|
+
# [id] The unique identifier for this user
|
8
|
+
# [username] This user's username
|
9
|
+
# [email] This user's email address (authenticated calls only)
|
10
|
+
#
|
11
|
+
class User
|
12
|
+
|
13
|
+
include Etsy::Model
|
14
|
+
|
15
|
+
attribute :id, :from => :user_id
|
16
|
+
attribute :username, :from => :login_name
|
17
|
+
attribute :email, :from => :primary_email
|
18
|
+
attribute :created, :from => :creation_tsz
|
19
|
+
|
20
|
+
association :profile, :from => 'Profile'
|
21
|
+
association :shops, :from => 'Shops'
|
22
|
+
|
23
|
+
# Retrieve one or more users by name or ID:
|
24
|
+
#
|
25
|
+
# Etsy::User.find('reagent')
|
26
|
+
#
|
27
|
+
# You can find multiple users by passing an array of identifiers:
|
28
|
+
#
|
29
|
+
# Etsy::User.find(['reagent', 'littletjane'])
|
30
|
+
#
|
31
|
+
def self.find(*identifiers_and_options)
|
32
|
+
find_one_or_more('users', identifiers_and_options)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Retrieve the currently authenticated user.
|
36
|
+
#
|
37
|
+
def self.myself(token, secret, options = {})
|
38
|
+
find('__SELF__', {:access_token => token, :access_secret => secret}.merge(options))
|
39
|
+
end
|
40
|
+
|
41
|
+
# The shop associated with this user.
|
42
|
+
#
|
43
|
+
def shop
|
44
|
+
@shop ||= shops.first
|
45
|
+
end
|
46
|
+
|
47
|
+
# The addresses associated with this user.
|
48
|
+
#
|
49
|
+
def addresses
|
50
|
+
options = (token && secret) ? {:access_token => token, :access_secret => secret} : {}
|
51
|
+
@addresses ||= Address.find(username, options)
|
52
|
+
end
|
53
|
+
|
54
|
+
# The profile associated with this user.
|
55
|
+
#
|
56
|
+
def profile
|
57
|
+
unless @profile
|
58
|
+
if associated_profile
|
59
|
+
@profile = Profile.new(associated_profile)
|
60
|
+
else
|
61
|
+
options = {:fields => 'user_id', :includes => 'Profile'}
|
62
|
+
options = options.merge(:access_token => token, :access_secret => secret) if (token && secret)
|
63
|
+
tmp = User.find(username, options)
|
64
|
+
@profile = Profile.new(tmp.associated_profile)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@profile
|
68
|
+
end
|
69
|
+
|
70
|
+
def shops
|
71
|
+
unless @shops
|
72
|
+
if associated_shops
|
73
|
+
@shops = associated_shops.map { |shop| Shop.new(shop) }
|
74
|
+
else
|
75
|
+
options = {:fields => 'user_id', :includes => 'Shops'}
|
76
|
+
options = options.merge(:access_token => token, :access_secret => secret) if (token && secret)
|
77
|
+
tmp = User.find(username, options)
|
78
|
+
@shops = tmp.associated_shops.map { |shop| Shop.new(shop) }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
@shops
|
82
|
+
end
|
83
|
+
|
84
|
+
# Time that this user was created
|
85
|
+
#
|
86
|
+
def created_at
|
87
|
+
Time.at(created)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Retrieve list of favorited items for this user
|
91
|
+
#
|
92
|
+
def favorites
|
93
|
+
unless @favorites
|
94
|
+
@favorites = Listing.find_all_user_favorite_listings(id, {:access_token => token, :access_secret => secret})
|
95
|
+
end
|
96
|
+
@favorites
|
97
|
+
end
|
98
|
+
|
99
|
+
#Return a set of listings that have been bought
|
100
|
+
#
|
101
|
+
def bought_listings
|
102
|
+
unless @bought_listings
|
103
|
+
@bought_listings = Listing.bought_listings(id, {:access_token => token, :access_secret => secret})
|
104
|
+
end
|
105
|
+
@bought_listings
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Etsy
|
2
|
+
module Variation
|
3
|
+
class PropertySet
|
4
|
+
# Used to find properties which the seller can vary (eg Size, Color, etc), and options associated with those properties (eg Inches)
|
5
|
+
#
|
6
|
+
# The variations stuff is complex. See https://www.etsy.com/developers/documentation/getting_started/variations for more info.
|
7
|
+
#
|
8
|
+
# Probably the most useful method here is qualifying_properties_for_property. This method pulls in data from a few sources to get
|
9
|
+
# you everything you need to set up your variation options.
|
10
|
+
#
|
11
|
+
# Eg: I want to have a few Length options on my listings, and I want to use the unit Inches, then:
|
12
|
+
# Etsy::Variation::PropertySet.qualifying_properties_for_property("Length")
|
13
|
+
# => [{
|
14
|
+
# "param"=>"sizing_scale",
|
15
|
+
# "description"=>"Sizing Scale",
|
16
|
+
# "options"=>{
|
17
|
+
# "Alpha" => 301,
|
18
|
+
# "Inches" => 327,
|
19
|
+
# "Centimeters" => 328,
|
20
|
+
# "Fluid Ounces" => 335,
|
21
|
+
# "Millilitres" => 336,
|
22
|
+
# "Litres" => 337,
|
23
|
+
# "Other => 329
|
24
|
+
# }
|
25
|
+
# }]
|
26
|
+
#
|
27
|
+
# This tells me I want to set the parameter sizing_scale to 327 when calling Etsy::Listing.add_variations.
|
28
|
+
|
29
|
+
include Etsy::Model
|
30
|
+
|
31
|
+
|
32
|
+
attributes :properties, :category_id, :options, :qualifiers,
|
33
|
+
:qualifying_properties
|
34
|
+
|
35
|
+
def self.all
|
36
|
+
@all ||= get("/property_sets")
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.find_property_by_name(name)
|
40
|
+
property = all.properties.detect {|prop_id, prop| prop["name"] == name}
|
41
|
+
if property
|
42
|
+
property_id, property_data = property
|
43
|
+
property_data
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.qualifying_properties_for_property(name)
|
48
|
+
property = find_property_by_name(name)
|
49
|
+
return nil unless property
|
50
|
+
property_id = property["property_id"]
|
51
|
+
|
52
|
+
qualifiers = all.qualifiers[property_id.to_s]
|
53
|
+
return [] unless qualifiers
|
54
|
+
|
55
|
+
qualifiers.map do |qualifier|
|
56
|
+
qualifying_properties = all.qualifying_properties[qualifier.fetch("property_id").to_s]
|
57
|
+
options = qualifier.fetch("options").inject({}) do |acc, opt_id|
|
58
|
+
acc.merge({
|
59
|
+
all.options.fetch(opt_id.to_s) => opt_id
|
60
|
+
})
|
61
|
+
end
|
62
|
+
{
|
63
|
+
"param" => qualifying_properties.fetch("param"),
|
64
|
+
"description" => qualifying_properties.fetch("description"),
|
65
|
+
"options" => options
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Etsy
|
2
|
+
class VerificationRequest # :nodoc:all
|
3
|
+
|
4
|
+
def client
|
5
|
+
@client ||= SecureClient.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def url
|
9
|
+
request_token.params[:login_url]
|
10
|
+
end
|
11
|
+
|
12
|
+
def request_token
|
13
|
+
@request_token ||= client.request_token
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/etsy/version.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"count":1,
|
3
|
+
"results":[
|
4
|
+
{ "shop_id": 8740774,
|
5
|
+
"status": "active",
|
6
|
+
"story_headline": "A shop long in the making...",
|
7
|
+
"story_leading_paragraph": "This is the leading paragraph",
|
8
|
+
"story": "I grew up with strong women in my family who all had a love of creating. My mom and grandma always encouraged a lifelong love of creating Working with glass, wire, and mineral components brings back my graduate school days, when I studied these items from a scientific point-of-view. Here's hoping I can create something that gives you a little sparkle in your life!",
|
9
|
+
"related_links": {
|
10
|
+
"link-0": {"title": "facebook", "url": "https://www.facebook.com/pebbleplusmetal/"},
|
11
|
+
"link-1": {"title": "pinterest", "url": "https://www.pinterest.com/PebblePlusMetal/pebble%2Bmetal/"}
|
12
|
+
},
|
13
|
+
"url": "https://www.etsy.com/shop/PebblePlusMetal/about"
|
14
|
+
}
|
15
|
+
]
|
16
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
{
|
2
|
+
"count":2,
|
3
|
+
"results":[
|
4
|
+
{"user_address_id":123,"user_id":9876,"name":"Tinker Bell","first_line":"123 Fake St.","second_line":null,"city":"BigCity","state":"XX","zip":"12345","country_id":209,"country_name":"United States"},
|
5
|
+
{"user_address_id":234,"user_id":9876,"name":"LittleCorp, Inc.","first_line":"123 Fake St.","second_line":null,"city":"BigCity","state":"XX","zip":"12345","country_id":209,"country_name":"United States"}
|
6
|
+
],
|
7
|
+
"params": {
|
8
|
+
"user_id":"PaisleyAnnHome","limit":25,"offset":0
|
9
|
+
},
|
10
|
+
"type":"UserAddress"
|
11
|
+
}
|
12
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
|
2
|
+
{
|
3
|
+
"count":4,
|
4
|
+
"results":
|
5
|
+
[
|
6
|
+
{
|
7
|
+
"property_id": 200,
|
8
|
+
"property_name": "Primary color",
|
9
|
+
"scale_id": null,
|
10
|
+
"scale_name": null,
|
11
|
+
"value_ids": [1213],
|
12
|
+
"values": ["Beige"]
|
13
|
+
},
|
14
|
+
{
|
15
|
+
"property_id": 52047899002,
|
16
|
+
"property_name": "Secondary color",
|
17
|
+
"scale_id": null,
|
18
|
+
"scale_name": null,
|
19
|
+
"value_ids": [1],
|
20
|
+
"values": ["Black"]
|
21
|
+
},
|
22
|
+
{
|
23
|
+
"property_id": 47626759834,
|
24
|
+
"property_name": "Height",
|
25
|
+
"scale_id": 5,
|
26
|
+
"scale_name": "Inches",
|
27
|
+
"value_ids": [0],
|
28
|
+
"values": ["15"]
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"property_id": 47626759898,
|
32
|
+
"property_name": "Width",
|
33
|
+
"scale_id": 5,
|
34
|
+
"scale_name": "Inches",
|
35
|
+
"value_ids": [0],
|
36
|
+
"values": ["25"]
|
37
|
+
}
|
38
|
+
],
|
39
|
+
"params":
|
40
|
+
{
|
41
|
+
"listing_id":"59495892"
|
42
|
+
},
|
43
|
+
"type":"ListingPropertyValue"
|
44
|
+
}
|