brand.dev 0.23.0 → 0.25.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d62936819f843f3b39b44d3e7ee2dcdb37d8bab316c6dff544032989d4c579e
4
- data.tar.gz: 0f5406cd25c0db18f69e9b41687c83582274a5aa6954fd776143b3cf2e127707
3
+ metadata.gz: 586503b2436acd1a836fdd867ebaf4258c5cb928320defd1b62b70c712439bc8
4
+ data.tar.gz: 3adcd4f046fd0a5d7ee98a6ee2367191e1925a3549a0a8a4b779d876d1c2fe72
5
5
  SHA512:
6
- metadata.gz: f90ff68d81d283086db18cdc24be921b97f2fb753049a716599a2a2b908537c45d88fbac9e9909b7824a28557fc34954e41acb4cef8edae0c140033fcc4c266b
7
- data.tar.gz: 40607397b880852fc184119bae74815d997a88c30d9d07b420ad0e4171e272b4a4f177dcaa2106e4b55cf446ee6a14e804406ecea613ef66b940f1565aa53b29
6
+ metadata.gz: 96a199073279aa10b42f908a1fc3705290eebb271559fd8249bfdb2d8cd157dbd32fdb177381139ebed4bc2b6154f6e1b251c6e4278f6f19091c0321d3408063
7
+ data.tar.gz: cb915b6992b9ab682c0a0ebec5b11d7245f18c18e23fbf649bd19595157733f99e5d68763b37e2443572fa9911fe32d4f406d3a72e173035a7342a17aafc56ac
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.25.0 (2026-02-22)
4
+
5
+ Full Changelog: [v0.24.0...v0.25.0](https://github.com/brand-dot-dev/ruby-sdk/compare/v0.24.0...v0.25.0)
6
+
7
+ ### Features
8
+
9
+ * **api:** api update ([a8001da](https://github.com/brand-dot-dev/ruby-sdk/commit/a8001da388a5bf764a6fe19b7df7bc3572ae3dce))
10
+
11
+
12
+ ### Chores
13
+
14
+ * **internal:** remove mock server code ([106d37c](https://github.com/brand-dot-dev/ruby-sdk/commit/106d37c53f7459910a897b4f675b97a003b73f7c))
15
+ * update mock server docs ([e60e130](https://github.com/brand-dot-dev/ruby-sdk/commit/e60e13027cec2ae0282f1ca4c4785d3586efe304))
16
+
17
+ ## 0.24.0 (2026-02-09)
18
+
19
+ Full Changelog: [v0.23.0...v0.24.0](https://github.com/brand-dot-dev/ruby-sdk/compare/v0.23.0...v0.24.0)
20
+
21
+ ### Features
22
+
23
+ * **api:** manual updates ([d51dcea](https://github.com/brand-dot-dev/ruby-sdk/commit/d51dcea705ad031b9010a391b7ed3a26c115beab))
24
+
3
25
  ## 0.23.0 (2026-02-07)
4
26
 
5
27
  Full Changelog: [v0.22.0...v0.23.0](https://github.com/brand-dot-dev/ruby-sdk/compare/v0.22.0...v0.23.0)
data/README.md CHANGED
@@ -26,7 +26,7 @@ To use this gem, install via Bundler by adding the following to your application
26
26
  <!-- x-release-please-start-version -->
27
27
 
28
28
  ```ruby
29
- gem "brand.dev", "~> 0.23.0"
29
+ gem "brand.dev", "~> 0.25.0"
30
30
  ```
31
31
 
32
32
  <!-- x-release-please-end -->
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BrandDev
4
+ module Models
5
+ # @see BrandDev::Resources::Brand#ai_product
6
+ class BrandAIProductParams < BrandDev::Internal::Type::BaseModel
7
+ extend BrandDev::Internal::Type::RequestParameters::Converter
8
+ include BrandDev::Internal::Type::RequestParameters
9
+
10
+ # @!attribute url
11
+ # The product page URL to extract product data from.
12
+ #
13
+ # @return [String]
14
+ required :url, String
15
+
16
+ # @!attribute timeout_ms
17
+ # Optional timeout in milliseconds for the request. Maximum allowed value is
18
+ # 300000ms (5 minutes).
19
+ #
20
+ # @return [Integer, nil]
21
+ optional :timeout_ms, Integer, api_name: :timeoutMS
22
+
23
+ # @!method initialize(url:, timeout_ms: nil, request_options: {})
24
+ # Some parameter documentations has been truncated, see
25
+ # {BrandDev::Models::BrandAIProductParams} for more details.
26
+ #
27
+ # @param url [String] The product page URL to extract product data from.
28
+ #
29
+ # @param timeout_ms [Integer] Optional timeout in milliseconds for the request. Maximum allowed value is 30000
30
+ #
31
+ # @param request_options [BrandDev::RequestOptions, Hash{Symbol=>Object}]
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BrandDev
4
+ module Models
5
+ # @see BrandDev::Resources::Brand#ai_product
6
+ class BrandAIProductResponse < BrandDev::Internal::Type::BaseModel
7
+ # @!attribute is_product_page
8
+ # Whether the given URL is a product detail page
9
+ #
10
+ # @return [Boolean, nil]
11
+ optional :is_product_page, BrandDev::Internal::Type::Boolean
12
+
13
+ # @!attribute platform
14
+ # The detected ecommerce platform, or null if not a product page
15
+ #
16
+ # @return [Symbol, BrandDev::Models::BrandAIProductResponse::Platform, nil]
17
+ optional :platform, enum: -> { BrandDev::Models::BrandAIProductResponse::Platform }, nil?: true
18
+
19
+ # @!attribute product
20
+ # The extracted product data, or null if not a product page
21
+ #
22
+ # @return [BrandDev::Models::BrandAIProductResponse::Product, nil]
23
+ optional :product, -> { BrandDev::Models::BrandAIProductResponse::Product }, nil?: true
24
+
25
+ # @!method initialize(is_product_page: nil, platform: nil, product: nil)
26
+ # @param is_product_page [Boolean] Whether the given URL is a product detail page
27
+ #
28
+ # @param platform [Symbol, BrandDev::Models::BrandAIProductResponse::Platform, nil] The detected ecommerce platform, or null if not a product page
29
+ #
30
+ # @param product [BrandDev::Models::BrandAIProductResponse::Product, nil] The extracted product data, or null if not a product page
31
+
32
+ # The detected ecommerce platform, or null if not a product page
33
+ #
34
+ # @see BrandDev::Models::BrandAIProductResponse#platform
35
+ module Platform
36
+ extend BrandDev::Internal::Type::Enum
37
+
38
+ AMAZON = :amazon
39
+ TIKTOK_SHOP = :tiktok_shop
40
+ ETSY = :etsy
41
+ GENERIC = :generic
42
+
43
+ # @!method self.values
44
+ # @return [Array<Symbol>]
45
+ end
46
+
47
+ # @see BrandDev::Models::BrandAIProductResponse#product
48
+ class Product < BrandDev::Internal::Type::BaseModel
49
+ # @!attribute description
50
+ # Description of the product
51
+ #
52
+ # @return [String]
53
+ required :description, String
54
+
55
+ # @!attribute features
56
+ # List of product features
57
+ #
58
+ # @return [Array<String>]
59
+ required :features, BrandDev::Internal::Type::ArrayOf[String]
60
+
61
+ # @!attribute images
62
+ # URLs to product images on the page (up to 7)
63
+ #
64
+ # @return [Array<String>]
65
+ required :images, BrandDev::Internal::Type::ArrayOf[String]
66
+
67
+ # @!attribute name
68
+ # Name of the product
69
+ #
70
+ # @return [String]
71
+ required :name, String
72
+
73
+ # @!attribute tags
74
+ # Tags associated with the product
75
+ #
76
+ # @return [Array<String>]
77
+ required :tags, BrandDev::Internal::Type::ArrayOf[String]
78
+
79
+ # @!attribute target_audience
80
+ # Target audience for the product (array of strings)
81
+ #
82
+ # @return [Array<String>]
83
+ required :target_audience, BrandDev::Internal::Type::ArrayOf[String]
84
+
85
+ # @!attribute billing_frequency
86
+ # Billing frequency for the product
87
+ #
88
+ # @return [Symbol, BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency, nil]
89
+ optional :billing_frequency,
90
+ enum: -> { BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency },
91
+ nil?: true
92
+
93
+ # @!attribute category
94
+ # Category of the product
95
+ #
96
+ # @return [String, nil]
97
+ optional :category, String, nil?: true
98
+
99
+ # @!attribute currency
100
+ # Currency code for the price (e.g., USD, EUR)
101
+ #
102
+ # @return [String, nil]
103
+ optional :currency, String, nil?: true
104
+
105
+ # @!attribute image_url
106
+ # URL to the product image
107
+ #
108
+ # @return [String, nil]
109
+ optional :image_url, String, nil?: true
110
+
111
+ # @!attribute price
112
+ # Price of the product
113
+ #
114
+ # @return [Float, nil]
115
+ optional :price, Float, nil?: true
116
+
117
+ # @!attribute pricing_model
118
+ # Pricing model for the product
119
+ #
120
+ # @return [Symbol, BrandDev::Models::BrandAIProductResponse::Product::PricingModel, nil]
121
+ optional :pricing_model,
122
+ enum: -> { BrandDev::Models::BrandAIProductResponse::Product::PricingModel },
123
+ nil?: true
124
+
125
+ # @!attribute url
126
+ # URL to the product page
127
+ #
128
+ # @return [String, nil]
129
+ optional :url, String, nil?: true
130
+
131
+ # @!method initialize(description:, features:, images:, name:, tags:, target_audience:, billing_frequency: nil, category: nil, currency: nil, image_url: nil, price: nil, pricing_model: nil, url: nil)
132
+ # The extracted product data, or null if not a product page
133
+ #
134
+ # @param description [String] Description of the product
135
+ #
136
+ # @param features [Array<String>] List of product features
137
+ #
138
+ # @param images [Array<String>] URLs to product images on the page (up to 7)
139
+ #
140
+ # @param name [String] Name of the product
141
+ #
142
+ # @param tags [Array<String>] Tags associated with the product
143
+ #
144
+ # @param target_audience [Array<String>] Target audience for the product (array of strings)
145
+ #
146
+ # @param billing_frequency [Symbol, BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency, nil] Billing frequency for the product
147
+ #
148
+ # @param category [String, nil] Category of the product
149
+ #
150
+ # @param currency [String, nil] Currency code for the price (e.g., USD, EUR)
151
+ #
152
+ # @param image_url [String, nil] URL to the product image
153
+ #
154
+ # @param price [Float, nil] Price of the product
155
+ #
156
+ # @param pricing_model [Symbol, BrandDev::Models::BrandAIProductResponse::Product::PricingModel, nil] Pricing model for the product
157
+ #
158
+ # @param url [String, nil] URL to the product page
159
+
160
+ # Billing frequency for the product
161
+ #
162
+ # @see BrandDev::Models::BrandAIProductResponse::Product#billing_frequency
163
+ module BillingFrequency
164
+ extend BrandDev::Internal::Type::Enum
165
+
166
+ MONTHLY = :monthly
167
+ YEARLY = :yearly
168
+ ONE_TIME = :one_time
169
+ USAGE_BASED = :usage_based
170
+
171
+ # @!method self.values
172
+ # @return [Array<Symbol>]
173
+ end
174
+
175
+ # Pricing model for the product
176
+ #
177
+ # @see BrandDev::Models::BrandAIProductResponse::Product#pricing_model
178
+ module PricingModel
179
+ extend BrandDev::Internal::Type::Enum
180
+
181
+ PER_SEAT = :per_seat
182
+ FLAT = :flat
183
+ TIERED = :tiered
184
+ FREEMIUM = :freemium
185
+ CUSTOM = :custom
186
+
187
+ # @!method self.values
188
+ # @return [Array<Symbol>]
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -27,6 +27,12 @@ module BrandDev
27
27
  # @return [Array<String>]
28
28
  required :features, BrandDev::Internal::Type::ArrayOf[String]
29
29
 
30
+ # @!attribute images
31
+ # URLs to product images on the page (up to 7)
32
+ #
33
+ # @return [Array<String>]
34
+ required :images, BrandDev::Internal::Type::ArrayOf[String]
35
+
30
36
  # @!attribute name
31
37
  # Name of the product
32
38
  #
@@ -91,11 +97,13 @@ module BrandDev
91
97
  # @return [String, nil]
92
98
  optional :url, String, nil?: true
93
99
 
94
- # @!method initialize(description:, features:, name:, tags:, target_audience:, billing_frequency: nil, category: nil, currency: nil, image_url: nil, price: nil, pricing_model: nil, url: nil)
100
+ # @!method initialize(description:, features:, images:, name:, tags:, target_audience:, billing_frequency: nil, category: nil, currency: nil, image_url: nil, price: nil, pricing_model: nil, url: nil)
95
101
  # @param description [String] Description of the product
96
102
  #
97
103
  # @param features [Array<String>] List of product features
98
104
  #
105
+ # @param images [Array<String>] URLs to product images on the page (up to 7)
106
+ #
99
107
  # @param name [String] Name of the product
100
108
  #
101
109
  # @param tags [Array<String>] Tags associated with the product
@@ -39,6 +39,8 @@ module BrandDev
39
39
  mod.define_sorbet_constant!(const) { T.type_alias { mod.to_sorbet_type } }
40
40
  end
41
41
 
42
+ BrandAIProductParams = BrandDev::Models::BrandAIProductParams
43
+
42
44
  BrandAIProductsParams = BrandDev::Models::BrandAIProductsParams
43
45
 
44
46
  BrandAIQueryParams = BrandDev::Models::BrandAIQueryParams
@@ -35,6 +35,35 @@ module BrandDev
35
35
  )
36
36
  end
37
37
 
38
+ # Some parameter documentations has been truncated, see
39
+ # {BrandDev::Models::BrandAIProductParams} for more details.
40
+ #
41
+ # Beta feature: Given a single URL, determines if it is a product detail page,
42
+ # classifies the platform/product type, and extracts the product information.
43
+ # Supports Amazon, TikTok Shop, Etsy, and generic ecommerce sites.
44
+ #
45
+ # @overload ai_product(url:, timeout_ms: nil, request_options: {})
46
+ #
47
+ # @param url [String] The product page URL to extract product data from.
48
+ #
49
+ # @param timeout_ms [Integer] Optional timeout in milliseconds for the request. Maximum allowed value is 30000
50
+ #
51
+ # @param request_options [BrandDev::RequestOptions, Hash{Symbol=>Object}, nil]
52
+ #
53
+ # @return [BrandDev::Models::BrandAIProductResponse]
54
+ #
55
+ # @see BrandDev::Models::BrandAIProductParams
56
+ def ai_product(params)
57
+ parsed, options = BrandDev::BrandAIProductParams.dump_request(params)
58
+ @client.request(
59
+ method: :post,
60
+ path: "brand/ai/product",
61
+ body: parsed,
62
+ model: BrandDev::Models::BrandAIProductResponse,
63
+ options: options
64
+ )
65
+ end
66
+
38
67
  # Some parameter documentations has been truncated, see
39
68
  # {BrandDev::Models::BrandAIProductsParams} for more details.
40
69
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BrandDev
4
- VERSION = "0.23.0"
4
+ VERSION = "0.25.0"
5
5
  end
data/lib/brand_dev.rb CHANGED
@@ -52,6 +52,8 @@ require_relative "brand_dev/errors"
52
52
  require_relative "brand_dev/internal/transport/base_client"
53
53
  require_relative "brand_dev/internal/transport/pooled_net_requester"
54
54
  require_relative "brand_dev/client"
55
+ require_relative "brand_dev/models/brand_ai_product_params"
56
+ require_relative "brand_dev/models/brand_ai_product_response"
55
57
  require_relative "brand_dev/models/brand_ai_products_params"
56
58
  require_relative "brand_dev/models/brand_ai_products_response"
57
59
  require_relative "brand_dev/models/brand_ai_query_params"
@@ -0,0 +1,56 @@
1
+ # typed: strong
2
+
3
+ module BrandDev
4
+ module Models
5
+ class BrandAIProductParams < BrandDev::Internal::Type::BaseModel
6
+ extend BrandDev::Internal::Type::RequestParameters::Converter
7
+ include BrandDev::Internal::Type::RequestParameters
8
+
9
+ OrHash =
10
+ T.type_alias do
11
+ T.any(BrandDev::BrandAIProductParams, BrandDev::Internal::AnyHash)
12
+ end
13
+
14
+ # The product page URL to extract product data from.
15
+ sig { returns(String) }
16
+ attr_accessor :url
17
+
18
+ # Optional timeout in milliseconds for the request. Maximum allowed value is
19
+ # 300000ms (5 minutes).
20
+ sig { returns(T.nilable(Integer)) }
21
+ attr_reader :timeout_ms
22
+
23
+ sig { params(timeout_ms: Integer).void }
24
+ attr_writer :timeout_ms
25
+
26
+ sig do
27
+ params(
28
+ url: String,
29
+ timeout_ms: Integer,
30
+ request_options: BrandDev::RequestOptions::OrHash
31
+ ).returns(T.attached_class)
32
+ end
33
+ def self.new(
34
+ # The product page URL to extract product data from.
35
+ url:,
36
+ # Optional timeout in milliseconds for the request. Maximum allowed value is
37
+ # 300000ms (5 minutes).
38
+ timeout_ms: nil,
39
+ request_options: {}
40
+ )
41
+ end
42
+
43
+ sig do
44
+ override.returns(
45
+ {
46
+ url: String,
47
+ timeout_ms: Integer,
48
+ request_options: BrandDev::RequestOptions
49
+ }
50
+ )
51
+ end
52
+ def to_hash
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,376 @@
1
+ # typed: strong
2
+
3
+ module BrandDev
4
+ module Models
5
+ class BrandAIProductResponse < BrandDev::Internal::Type::BaseModel
6
+ OrHash =
7
+ T.type_alias do
8
+ T.any(
9
+ BrandDev::Models::BrandAIProductResponse,
10
+ BrandDev::Internal::AnyHash
11
+ )
12
+ end
13
+
14
+ # Whether the given URL is a product detail page
15
+ sig { returns(T.nilable(T::Boolean)) }
16
+ attr_reader :is_product_page
17
+
18
+ sig { params(is_product_page: T::Boolean).void }
19
+ attr_writer :is_product_page
20
+
21
+ # The detected ecommerce platform, or null if not a product page
22
+ sig do
23
+ returns(
24
+ T.nilable(
25
+ BrandDev::Models::BrandAIProductResponse::Platform::TaggedSymbol
26
+ )
27
+ )
28
+ end
29
+ attr_accessor :platform
30
+
31
+ # The extracted product data, or null if not a product page
32
+ sig do
33
+ returns(T.nilable(BrandDev::Models::BrandAIProductResponse::Product))
34
+ end
35
+ attr_reader :product
36
+
37
+ sig do
38
+ params(
39
+ product:
40
+ T.nilable(BrandDev::Models::BrandAIProductResponse::Product::OrHash)
41
+ ).void
42
+ end
43
+ attr_writer :product
44
+
45
+ sig do
46
+ params(
47
+ is_product_page: T::Boolean,
48
+ platform:
49
+ T.nilable(
50
+ BrandDev::Models::BrandAIProductResponse::Platform::OrSymbol
51
+ ),
52
+ product:
53
+ T.nilable(BrandDev::Models::BrandAIProductResponse::Product::OrHash)
54
+ ).returns(T.attached_class)
55
+ end
56
+ def self.new(
57
+ # Whether the given URL is a product detail page
58
+ is_product_page: nil,
59
+ # The detected ecommerce platform, or null if not a product page
60
+ platform: nil,
61
+ # The extracted product data, or null if not a product page
62
+ product: nil
63
+ )
64
+ end
65
+
66
+ sig do
67
+ override.returns(
68
+ {
69
+ is_product_page: T::Boolean,
70
+ platform:
71
+ T.nilable(
72
+ BrandDev::Models::BrandAIProductResponse::Platform::TaggedSymbol
73
+ ),
74
+ product:
75
+ T.nilable(BrandDev::Models::BrandAIProductResponse::Product)
76
+ }
77
+ )
78
+ end
79
+ def to_hash
80
+ end
81
+
82
+ # The detected ecommerce platform, or null if not a product page
83
+ module Platform
84
+ extend BrandDev::Internal::Type::Enum
85
+
86
+ TaggedSymbol =
87
+ T.type_alias do
88
+ T.all(Symbol, BrandDev::Models::BrandAIProductResponse::Platform)
89
+ end
90
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
91
+
92
+ AMAZON =
93
+ T.let(
94
+ :amazon,
95
+ BrandDev::Models::BrandAIProductResponse::Platform::TaggedSymbol
96
+ )
97
+ TIKTOK_SHOP =
98
+ T.let(
99
+ :tiktok_shop,
100
+ BrandDev::Models::BrandAIProductResponse::Platform::TaggedSymbol
101
+ )
102
+ ETSY =
103
+ T.let(
104
+ :etsy,
105
+ BrandDev::Models::BrandAIProductResponse::Platform::TaggedSymbol
106
+ )
107
+ GENERIC =
108
+ T.let(
109
+ :generic,
110
+ BrandDev::Models::BrandAIProductResponse::Platform::TaggedSymbol
111
+ )
112
+
113
+ sig do
114
+ override.returns(
115
+ T::Array[
116
+ BrandDev::Models::BrandAIProductResponse::Platform::TaggedSymbol
117
+ ]
118
+ )
119
+ end
120
+ def self.values
121
+ end
122
+ end
123
+
124
+ class Product < BrandDev::Internal::Type::BaseModel
125
+ OrHash =
126
+ T.type_alias do
127
+ T.any(
128
+ BrandDev::Models::BrandAIProductResponse::Product,
129
+ BrandDev::Internal::AnyHash
130
+ )
131
+ end
132
+
133
+ # Description of the product
134
+ sig { returns(String) }
135
+ attr_accessor :description
136
+
137
+ # List of product features
138
+ sig { returns(T::Array[String]) }
139
+ attr_accessor :features
140
+
141
+ # URLs to product images on the page (up to 7)
142
+ sig { returns(T::Array[String]) }
143
+ attr_accessor :images
144
+
145
+ # Name of the product
146
+ sig { returns(String) }
147
+ attr_accessor :name
148
+
149
+ # Tags associated with the product
150
+ sig { returns(T::Array[String]) }
151
+ attr_accessor :tags
152
+
153
+ # Target audience for the product (array of strings)
154
+ sig { returns(T::Array[String]) }
155
+ attr_accessor :target_audience
156
+
157
+ # Billing frequency for the product
158
+ sig do
159
+ returns(
160
+ T.nilable(
161
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
162
+ )
163
+ )
164
+ end
165
+ attr_accessor :billing_frequency
166
+
167
+ # Category of the product
168
+ sig { returns(T.nilable(String)) }
169
+ attr_accessor :category
170
+
171
+ # Currency code for the price (e.g., USD, EUR)
172
+ sig { returns(T.nilable(String)) }
173
+ attr_accessor :currency
174
+
175
+ # URL to the product image
176
+ sig { returns(T.nilable(String)) }
177
+ attr_accessor :image_url
178
+
179
+ # Price of the product
180
+ sig { returns(T.nilable(Float)) }
181
+ attr_accessor :price
182
+
183
+ # Pricing model for the product
184
+ sig do
185
+ returns(
186
+ T.nilable(
187
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
188
+ )
189
+ )
190
+ end
191
+ attr_accessor :pricing_model
192
+
193
+ # URL to the product page
194
+ sig { returns(T.nilable(String)) }
195
+ attr_accessor :url
196
+
197
+ # The extracted product data, or null if not a product page
198
+ sig do
199
+ params(
200
+ description: String,
201
+ features: T::Array[String],
202
+ images: T::Array[String],
203
+ name: String,
204
+ tags: T::Array[String],
205
+ target_audience: T::Array[String],
206
+ billing_frequency:
207
+ T.nilable(
208
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::OrSymbol
209
+ ),
210
+ category: T.nilable(String),
211
+ currency: T.nilable(String),
212
+ image_url: T.nilable(String),
213
+ price: T.nilable(Float),
214
+ pricing_model:
215
+ T.nilable(
216
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::OrSymbol
217
+ ),
218
+ url: T.nilable(String)
219
+ ).returns(T.attached_class)
220
+ end
221
+ def self.new(
222
+ # Description of the product
223
+ description:,
224
+ # List of product features
225
+ features:,
226
+ # URLs to product images on the page (up to 7)
227
+ images:,
228
+ # Name of the product
229
+ name:,
230
+ # Tags associated with the product
231
+ tags:,
232
+ # Target audience for the product (array of strings)
233
+ target_audience:,
234
+ # Billing frequency for the product
235
+ billing_frequency: nil,
236
+ # Category of the product
237
+ category: nil,
238
+ # Currency code for the price (e.g., USD, EUR)
239
+ currency: nil,
240
+ # URL to the product image
241
+ image_url: nil,
242
+ # Price of the product
243
+ price: nil,
244
+ # Pricing model for the product
245
+ pricing_model: nil,
246
+ # URL to the product page
247
+ url: nil
248
+ )
249
+ end
250
+
251
+ sig do
252
+ override.returns(
253
+ {
254
+ description: String,
255
+ features: T::Array[String],
256
+ images: T::Array[String],
257
+ name: String,
258
+ tags: T::Array[String],
259
+ target_audience: T::Array[String],
260
+ billing_frequency:
261
+ T.nilable(
262
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
263
+ ),
264
+ category: T.nilable(String),
265
+ currency: T.nilable(String),
266
+ image_url: T.nilable(String),
267
+ price: T.nilable(Float),
268
+ pricing_model:
269
+ T.nilable(
270
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
271
+ ),
272
+ url: T.nilable(String)
273
+ }
274
+ )
275
+ end
276
+ def to_hash
277
+ end
278
+
279
+ # Billing frequency for the product
280
+ module BillingFrequency
281
+ extend BrandDev::Internal::Type::Enum
282
+
283
+ TaggedSymbol =
284
+ T.type_alias do
285
+ T.all(
286
+ Symbol,
287
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency
288
+ )
289
+ end
290
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
291
+
292
+ MONTHLY =
293
+ T.let(
294
+ :monthly,
295
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
296
+ )
297
+ YEARLY =
298
+ T.let(
299
+ :yearly,
300
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
301
+ )
302
+ ONE_TIME =
303
+ T.let(
304
+ :one_time,
305
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
306
+ )
307
+ USAGE_BASED =
308
+ T.let(
309
+ :usage_based,
310
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
311
+ )
312
+
313
+ sig do
314
+ override.returns(
315
+ T::Array[
316
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
317
+ ]
318
+ )
319
+ end
320
+ def self.values
321
+ end
322
+ end
323
+
324
+ # Pricing model for the product
325
+ module PricingModel
326
+ extend BrandDev::Internal::Type::Enum
327
+
328
+ TaggedSymbol =
329
+ T.type_alias do
330
+ T.all(
331
+ Symbol,
332
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel
333
+ )
334
+ end
335
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
336
+
337
+ PER_SEAT =
338
+ T.let(
339
+ :per_seat,
340
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
341
+ )
342
+ FLAT =
343
+ T.let(
344
+ :flat,
345
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
346
+ )
347
+ TIERED =
348
+ T.let(
349
+ :tiered,
350
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
351
+ )
352
+ FREEMIUM =
353
+ T.let(
354
+ :freemium,
355
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
356
+ )
357
+ CUSTOM =
358
+ T.let(
359
+ :custom,
360
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
361
+ )
362
+
363
+ sig do
364
+ override.returns(
365
+ T::Array[
366
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
367
+ ]
368
+ )
369
+ end
370
+ def self.values
371
+ end
372
+ end
373
+ end
374
+ end
375
+ end
376
+ end
@@ -69,6 +69,10 @@ module BrandDev
69
69
  sig { returns(T::Array[String]) }
70
70
  attr_accessor :features
71
71
 
72
+ # URLs to product images on the page (up to 7)
73
+ sig { returns(T::Array[String]) }
74
+ attr_accessor :images
75
+
72
76
  # Name of the product
73
77
  sig { returns(String) }
74
78
  attr_accessor :name
@@ -125,6 +129,7 @@ module BrandDev
125
129
  params(
126
130
  description: String,
127
131
  features: T::Array[String],
132
+ images: T::Array[String],
128
133
  name: String,
129
134
  tags: T::Array[String],
130
135
  target_audience: T::Array[String],
@@ -148,6 +153,8 @@ module BrandDev
148
153
  description:,
149
154
  # List of product features
150
155
  features:,
156
+ # URLs to product images on the page (up to 7)
157
+ images:,
151
158
  # Name of the product
152
159
  name:,
153
160
  # Tags associated with the product
@@ -176,6 +183,7 @@ module BrandDev
176
183
  {
177
184
  description: String,
178
185
  features: T::Array[String],
186
+ images: T::Array[String],
179
187
  name: String,
180
188
  tags: T::Array[String],
181
189
  target_audience: T::Array[String],
@@ -1,6 +1,8 @@
1
1
  # typed: strong
2
2
 
3
3
  module BrandDev
4
+ BrandAIProductParams = BrandDev::Models::BrandAIProductParams
5
+
4
6
  BrandAIProductsParams = BrandDev::Models::BrandAIProductsParams
5
7
 
6
8
  BrandAIQueryParams = BrandDev::Models::BrandAIQueryParams
@@ -34,6 +34,26 @@ module BrandDev
34
34
  )
35
35
  end
36
36
 
37
+ # Beta feature: Given a single URL, determines if it is a product detail page,
38
+ # classifies the platform/product type, and extracts the product information.
39
+ # Supports Amazon, TikTok Shop, Etsy, and generic ecommerce sites.
40
+ sig do
41
+ params(
42
+ url: String,
43
+ timeout_ms: Integer,
44
+ request_options: BrandDev::RequestOptions::OrHash
45
+ ).returns(BrandDev::Models::BrandAIProductResponse)
46
+ end
47
+ def ai_product(
48
+ # The product page URL to extract product data from.
49
+ url:,
50
+ # Optional timeout in milliseconds for the request. Maximum allowed value is
51
+ # 300000ms (5 minutes).
52
+ timeout_ms: nil,
53
+ request_options: {}
54
+ )
55
+ end
56
+
37
57
  # Beta feature: Extract product information from a brand's website. Brand.dev will
38
58
  # analyze the website and return a list of products with details such as name,
39
59
  # description, image, pricing, features, and more.
@@ -0,0 +1,30 @@
1
+ module BrandDev
2
+ module Models
3
+ type brand_ai_product_params =
4
+ { url: String, timeout_ms: Integer }
5
+ & BrandDev::Internal::Type::request_parameters
6
+
7
+ class BrandAIProductParams < BrandDev::Internal::Type::BaseModel
8
+ extend BrandDev::Internal::Type::RequestParameters::Converter
9
+ include BrandDev::Internal::Type::RequestParameters
10
+
11
+ attr_accessor url: String
12
+
13
+ attr_reader timeout_ms: Integer?
14
+
15
+ def timeout_ms=: (Integer) -> Integer
16
+
17
+ def initialize: (
18
+ url: String,
19
+ ?timeout_ms: Integer,
20
+ ?request_options: BrandDev::request_opts
21
+ ) -> void
22
+
23
+ def to_hash: -> {
24
+ url: String,
25
+ timeout_ms: Integer,
26
+ request_options: BrandDev::RequestOptions
27
+ }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,149 @@
1
+ module BrandDev
2
+ module Models
3
+ type brand_ai_product_response =
4
+ {
5
+ is_product_page: bool,
6
+ platform: BrandDev::Models::BrandAIProductResponse::platform?,
7
+ product: BrandDev::Models::BrandAIProductResponse::Product?
8
+ }
9
+
10
+ class BrandAIProductResponse < BrandDev::Internal::Type::BaseModel
11
+ attr_reader is_product_page: bool?
12
+
13
+ def is_product_page=: (bool) -> bool
14
+
15
+ attr_accessor platform: BrandDev::Models::BrandAIProductResponse::platform?
16
+
17
+ attr_accessor product: BrandDev::Models::BrandAIProductResponse::Product?
18
+
19
+ def initialize: (
20
+ ?is_product_page: bool,
21
+ ?platform: BrandDev::Models::BrandAIProductResponse::platform?,
22
+ ?product: BrandDev::Models::BrandAIProductResponse::Product?
23
+ ) -> void
24
+
25
+ def to_hash: -> {
26
+ is_product_page: bool,
27
+ platform: BrandDev::Models::BrandAIProductResponse::platform?,
28
+ product: BrandDev::Models::BrandAIProductResponse::Product?
29
+ }
30
+
31
+ type platform = :amazon | :tiktok_shop | :etsy | :generic
32
+
33
+ module Platform
34
+ extend BrandDev::Internal::Type::Enum
35
+
36
+ AMAZON: :amazon
37
+ TIKTOK_SHOP: :tiktok_shop
38
+ ETSY: :etsy
39
+ GENERIC: :generic
40
+
41
+ def self?.values: -> ::Array[BrandDev::Models::BrandAIProductResponse::platform]
42
+ end
43
+
44
+ type product =
45
+ {
46
+ description: String,
47
+ features: ::Array[String],
48
+ images: ::Array[String],
49
+ name: String,
50
+ tags: ::Array[String],
51
+ target_audience: ::Array[String],
52
+ billing_frequency: BrandDev::Models::BrandAIProductResponse::Product::billing_frequency?,
53
+ category: String?,
54
+ currency: String?,
55
+ image_url: String?,
56
+ price: Float?,
57
+ pricing_model: BrandDev::Models::BrandAIProductResponse::Product::pricing_model?,
58
+ url: String?
59
+ }
60
+
61
+ class Product < BrandDev::Internal::Type::BaseModel
62
+ attr_accessor description: String
63
+
64
+ attr_accessor features: ::Array[String]
65
+
66
+ attr_accessor images: ::Array[String]
67
+
68
+ attr_accessor name: String
69
+
70
+ attr_accessor tags: ::Array[String]
71
+
72
+ attr_accessor target_audience: ::Array[String]
73
+
74
+ attr_accessor billing_frequency: BrandDev::Models::BrandAIProductResponse::Product::billing_frequency?
75
+
76
+ attr_accessor category: String?
77
+
78
+ attr_accessor currency: String?
79
+
80
+ attr_accessor image_url: String?
81
+
82
+ attr_accessor price: Float?
83
+
84
+ attr_accessor pricing_model: BrandDev::Models::BrandAIProductResponse::Product::pricing_model?
85
+
86
+ attr_accessor url: String?
87
+
88
+ def initialize: (
89
+ description: String,
90
+ features: ::Array[String],
91
+ images: ::Array[String],
92
+ name: String,
93
+ tags: ::Array[String],
94
+ target_audience: ::Array[String],
95
+ ?billing_frequency: BrandDev::Models::BrandAIProductResponse::Product::billing_frequency?,
96
+ ?category: String?,
97
+ ?currency: String?,
98
+ ?image_url: String?,
99
+ ?price: Float?,
100
+ ?pricing_model: BrandDev::Models::BrandAIProductResponse::Product::pricing_model?,
101
+ ?url: String?
102
+ ) -> void
103
+
104
+ def to_hash: -> {
105
+ description: String,
106
+ features: ::Array[String],
107
+ images: ::Array[String],
108
+ name: String,
109
+ tags: ::Array[String],
110
+ target_audience: ::Array[String],
111
+ billing_frequency: BrandDev::Models::BrandAIProductResponse::Product::billing_frequency?,
112
+ category: String?,
113
+ currency: String?,
114
+ image_url: String?,
115
+ price: Float?,
116
+ pricing_model: BrandDev::Models::BrandAIProductResponse::Product::pricing_model?,
117
+ url: String?
118
+ }
119
+
120
+ type billing_frequency = :monthly | :yearly | :one_time | :usage_based
121
+
122
+ module BillingFrequency
123
+ extend BrandDev::Internal::Type::Enum
124
+
125
+ MONTHLY: :monthly
126
+ YEARLY: :yearly
127
+ ONE_TIME: :one_time
128
+ USAGE_BASED: :usage_based
129
+
130
+ def self?.values: -> ::Array[BrandDev::Models::BrandAIProductResponse::Product::billing_frequency]
131
+ end
132
+
133
+ type pricing_model = :per_seat | :flat | :tiered | :freemium | :custom
134
+
135
+ module PricingModel
136
+ extend BrandDev::Internal::Type::Enum
137
+
138
+ PER_SEAT: :per_seat
139
+ FLAT: :flat
140
+ TIERED: :tiered
141
+ FREEMIUM: :freemium
142
+ CUSTOM: :custom
143
+
144
+ def self?.values: -> ::Array[BrandDev::Models::BrandAIProductResponse::Product::pricing_model]
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -22,6 +22,7 @@ module BrandDev
22
22
  {
23
23
  description: String,
24
24
  features: ::Array[String],
25
+ images: ::Array[String],
25
26
  name: String,
26
27
  tags: ::Array[String],
27
28
  target_audience: ::Array[String],
@@ -39,6 +40,8 @@ module BrandDev
39
40
 
40
41
  attr_accessor features: ::Array[String]
41
42
 
43
+ attr_accessor images: ::Array[String]
44
+
42
45
  attr_accessor name: String
43
46
 
44
47
  attr_accessor tags: ::Array[String]
@@ -62,6 +65,7 @@ module BrandDev
62
65
  def initialize: (
63
66
  description: String,
64
67
  features: ::Array[String],
68
+ images: ::Array[String],
65
69
  name: String,
66
70
  tags: ::Array[String],
67
71
  target_audience: ::Array[String],
@@ -77,6 +81,7 @@ module BrandDev
77
81
  def to_hash: -> {
78
82
  description: String,
79
83
  features: ::Array[String],
84
+ images: ::Array[String],
80
85
  name: String,
81
86
  tags: ::Array[String],
82
87
  target_audience: ::Array[String],
@@ -1,4 +1,6 @@
1
1
  module BrandDev
2
+ class BrandAIProductParams = BrandDev::Models::BrandAIProductParams
3
+
2
4
  class BrandAIProductsParams = BrandDev::Models::BrandAIProductsParams
3
5
 
4
6
  class BrandAIQueryParams = BrandDev::Models::BrandAIQueryParams
@@ -9,6 +9,12 @@ module BrandDev
9
9
  ?request_options: BrandDev::request_opts
10
10
  ) -> BrandDev::Models::BrandRetrieveResponse
11
11
 
12
+ def ai_product: (
13
+ url: String,
14
+ ?timeout_ms: Integer,
15
+ ?request_options: BrandDev::request_opts
16
+ ) -> BrandDev::Models::BrandAIProductResponse
17
+
12
18
  def ai_products: (
13
19
  domain: String,
14
20
  direct_url: String,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brand.dev
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.0
4
+ version: 0.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brand Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-07 00:00:00.000000000 Z
11
+ date: 2026-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cgi
@@ -68,6 +68,8 @@ files:
68
68
  - lib/brand_dev/internal/type/unknown.rb
69
69
  - lib/brand_dev/internal/util.rb
70
70
  - lib/brand_dev/models.rb
71
+ - lib/brand_dev/models/brand_ai_product_params.rb
72
+ - lib/brand_dev/models/brand_ai_product_response.rb
71
73
  - lib/brand_dev/models/brand_ai_products_params.rb
72
74
  - lib/brand_dev/models/brand_ai_products_response.rb
73
75
  - lib/brand_dev/models/brand_ai_query_params.rb
@@ -121,6 +123,8 @@ files:
121
123
  - rbi/brand_dev/internal/type/unknown.rbi
122
124
  - rbi/brand_dev/internal/util.rbi
123
125
  - rbi/brand_dev/models.rbi
126
+ - rbi/brand_dev/models/brand_ai_product_params.rbi
127
+ - rbi/brand_dev/models/brand_ai_product_response.rbi
124
128
  - rbi/brand_dev/models/brand_ai_products_params.rbi
125
129
  - rbi/brand_dev/models/brand_ai_products_response.rbi
126
130
  - rbi/brand_dev/models/brand_ai_query_params.rbi
@@ -173,6 +177,8 @@ files:
173
177
  - sig/brand_dev/internal/type/unknown.rbs
174
178
  - sig/brand_dev/internal/util.rbs
175
179
  - sig/brand_dev/models.rbs
180
+ - sig/brand_dev/models/brand_ai_product_params.rbs
181
+ - sig/brand_dev/models/brand_ai_product_response.rbs
176
182
  - sig/brand_dev/models/brand_ai_products_params.rbs
177
183
  - sig/brand_dev/models/brand_ai_products_response.rbs
178
184
  - sig/brand_dev/models/brand_ai_query_params.rbs