brand.dev 0.23.0 → 0.24.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: a00f1524f31f5130cddc6248ee9013aa339c420fb8a99ee4236d89cf80969f82
4
+ data.tar.gz: '09f8dec8b06ddad368899fdf113dda2429a66f032d099f52a791f41c41cbb528'
5
5
  SHA512:
6
- metadata.gz: f90ff68d81d283086db18cdc24be921b97f2fb753049a716599a2a2b908537c45d88fbac9e9909b7824a28557fc34954e41acb4cef8edae0c140033fcc4c266b
7
- data.tar.gz: 40607397b880852fc184119bae74815d997a88c30d9d07b420ad0e4171e272b4a4f177dcaa2106e4b55cf446ee6a14e804406ecea613ef66b940f1565aa53b29
6
+ metadata.gz: c96b78a973e6c4e036cd0c55870f7dfa3ea5623e38446d47ecfae9274cb801bc76fa91513add1135e120474b855dab373e046ca3849495b0a775806d3b5eb6d1
7
+ data.tar.gz: 70c05ab291fd1bafe0cd434ac01f89d6e8afea599f8935dbb29bf1b242bbc3b1b1a14bfec6c49e1a424b4ccd1362492a13a02285422fca0ef8feba1aa2771170
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.24.0 (2026-02-09)
4
+
5
+ Full Changelog: [v0.23.0...v0.24.0](https://github.com/brand-dot-dev/ruby-sdk/compare/v0.23.0...v0.24.0)
6
+
7
+ ### Features
8
+
9
+ * **api:** manual updates ([d51dcea](https://github.com/brand-dot-dev/ruby-sdk/commit/d51dcea705ad031b9010a391b7ed3a26c115beab))
10
+
3
11
  ## 0.23.0 (2026-02-07)
4
12
 
5
13
  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.24.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,185 @@
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 name
62
+ # Name of the product
63
+ #
64
+ # @return [String]
65
+ required :name, String
66
+
67
+ # @!attribute tags
68
+ # Tags associated with the product
69
+ #
70
+ # @return [Array<String>]
71
+ required :tags, BrandDev::Internal::Type::ArrayOf[String]
72
+
73
+ # @!attribute target_audience
74
+ # Target audience for the product (array of strings)
75
+ #
76
+ # @return [Array<String>]
77
+ required :target_audience, BrandDev::Internal::Type::ArrayOf[String]
78
+
79
+ # @!attribute billing_frequency
80
+ # Billing frequency for the product
81
+ #
82
+ # @return [Symbol, BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency, nil]
83
+ optional :billing_frequency,
84
+ enum: -> { BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency },
85
+ nil?: true
86
+
87
+ # @!attribute category
88
+ # Category of the product
89
+ #
90
+ # @return [String, nil]
91
+ optional :category, String, nil?: true
92
+
93
+ # @!attribute currency
94
+ # Currency code for the price (e.g., USD, EUR)
95
+ #
96
+ # @return [String, nil]
97
+ optional :currency, String, nil?: true
98
+
99
+ # @!attribute image_url
100
+ # URL to the product image
101
+ #
102
+ # @return [String, nil]
103
+ optional :image_url, String, nil?: true
104
+
105
+ # @!attribute price
106
+ # Price of the product
107
+ #
108
+ # @return [Float, nil]
109
+ optional :price, Float, nil?: true
110
+
111
+ # @!attribute pricing_model
112
+ # Pricing model for the product
113
+ #
114
+ # @return [Symbol, BrandDev::Models::BrandAIProductResponse::Product::PricingModel, nil]
115
+ optional :pricing_model,
116
+ enum: -> { BrandDev::Models::BrandAIProductResponse::Product::PricingModel },
117
+ nil?: true
118
+
119
+ # @!attribute url
120
+ # URL to the product page
121
+ #
122
+ # @return [String, nil]
123
+ optional :url, String, nil?: true
124
+
125
+ # @!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)
126
+ # The extracted product data, or null if not a product page
127
+ #
128
+ # @param description [String] Description of the product
129
+ #
130
+ # @param features [Array<String>] List of product features
131
+ #
132
+ # @param name [String] Name of the product
133
+ #
134
+ # @param tags [Array<String>] Tags associated with the product
135
+ #
136
+ # @param target_audience [Array<String>] Target audience for the product (array of strings)
137
+ #
138
+ # @param billing_frequency [Symbol, BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency, nil] Billing frequency for the product
139
+ #
140
+ # @param category [String, nil] Category of the product
141
+ #
142
+ # @param currency [String, nil] Currency code for the price (e.g., USD, EUR)
143
+ #
144
+ # @param image_url [String, nil] URL to the product image
145
+ #
146
+ # @param price [Float, nil] Price of the product
147
+ #
148
+ # @param pricing_model [Symbol, BrandDev::Models::BrandAIProductResponse::Product::PricingModel, nil] Pricing model for the product
149
+ #
150
+ # @param url [String, nil] URL to the product page
151
+
152
+ # Billing frequency for the product
153
+ #
154
+ # @see BrandDev::Models::BrandAIProductResponse::Product#billing_frequency
155
+ module BillingFrequency
156
+ extend BrandDev::Internal::Type::Enum
157
+
158
+ MONTHLY = :monthly
159
+ YEARLY = :yearly
160
+ ONE_TIME = :one_time
161
+ USAGE_BASED = :usage_based
162
+
163
+ # @!method self.values
164
+ # @return [Array<Symbol>]
165
+ end
166
+
167
+ # Pricing model for the product
168
+ #
169
+ # @see BrandDev::Models::BrandAIProductResponse::Product#pricing_model
170
+ module PricingModel
171
+ extend BrandDev::Internal::Type::Enum
172
+
173
+ PER_SEAT = :per_seat
174
+ FLAT = :flat
175
+ TIERED = :tiered
176
+ FREEMIUM = :freemium
177
+ CUSTOM = :custom
178
+
179
+ # @!method self.values
180
+ # @return [Array<Symbol>]
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -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.24.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,368 @@
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
+ # Name of the product
142
+ sig { returns(String) }
143
+ attr_accessor :name
144
+
145
+ # Tags associated with the product
146
+ sig { returns(T::Array[String]) }
147
+ attr_accessor :tags
148
+
149
+ # Target audience for the product (array of strings)
150
+ sig { returns(T::Array[String]) }
151
+ attr_accessor :target_audience
152
+
153
+ # Billing frequency for the product
154
+ sig do
155
+ returns(
156
+ T.nilable(
157
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
158
+ )
159
+ )
160
+ end
161
+ attr_accessor :billing_frequency
162
+
163
+ # Category of the product
164
+ sig { returns(T.nilable(String)) }
165
+ attr_accessor :category
166
+
167
+ # Currency code for the price (e.g., USD, EUR)
168
+ sig { returns(T.nilable(String)) }
169
+ attr_accessor :currency
170
+
171
+ # URL to the product image
172
+ sig { returns(T.nilable(String)) }
173
+ attr_accessor :image_url
174
+
175
+ # Price of the product
176
+ sig { returns(T.nilable(Float)) }
177
+ attr_accessor :price
178
+
179
+ # Pricing model for the product
180
+ sig do
181
+ returns(
182
+ T.nilable(
183
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
184
+ )
185
+ )
186
+ end
187
+ attr_accessor :pricing_model
188
+
189
+ # URL to the product page
190
+ sig { returns(T.nilable(String)) }
191
+ attr_accessor :url
192
+
193
+ # The extracted product data, or null if not a product page
194
+ sig do
195
+ params(
196
+ description: String,
197
+ features: T::Array[String],
198
+ name: String,
199
+ tags: T::Array[String],
200
+ target_audience: T::Array[String],
201
+ billing_frequency:
202
+ T.nilable(
203
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::OrSymbol
204
+ ),
205
+ category: T.nilable(String),
206
+ currency: T.nilable(String),
207
+ image_url: T.nilable(String),
208
+ price: T.nilable(Float),
209
+ pricing_model:
210
+ T.nilable(
211
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::OrSymbol
212
+ ),
213
+ url: T.nilable(String)
214
+ ).returns(T.attached_class)
215
+ end
216
+ def self.new(
217
+ # Description of the product
218
+ description:,
219
+ # List of product features
220
+ features:,
221
+ # Name of the product
222
+ name:,
223
+ # Tags associated with the product
224
+ tags:,
225
+ # Target audience for the product (array of strings)
226
+ target_audience:,
227
+ # Billing frequency for the product
228
+ billing_frequency: nil,
229
+ # Category of the product
230
+ category: nil,
231
+ # Currency code for the price (e.g., USD, EUR)
232
+ currency: nil,
233
+ # URL to the product image
234
+ image_url: nil,
235
+ # Price of the product
236
+ price: nil,
237
+ # Pricing model for the product
238
+ pricing_model: nil,
239
+ # URL to the product page
240
+ url: nil
241
+ )
242
+ end
243
+
244
+ sig do
245
+ override.returns(
246
+ {
247
+ description: String,
248
+ features: T::Array[String],
249
+ name: String,
250
+ tags: T::Array[String],
251
+ target_audience: T::Array[String],
252
+ billing_frequency:
253
+ T.nilable(
254
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
255
+ ),
256
+ category: T.nilable(String),
257
+ currency: T.nilable(String),
258
+ image_url: T.nilable(String),
259
+ price: T.nilable(Float),
260
+ pricing_model:
261
+ T.nilable(
262
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
263
+ ),
264
+ url: T.nilable(String)
265
+ }
266
+ )
267
+ end
268
+ def to_hash
269
+ end
270
+
271
+ # Billing frequency for the product
272
+ module BillingFrequency
273
+ extend BrandDev::Internal::Type::Enum
274
+
275
+ TaggedSymbol =
276
+ T.type_alias do
277
+ T.all(
278
+ Symbol,
279
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency
280
+ )
281
+ end
282
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
283
+
284
+ MONTHLY =
285
+ T.let(
286
+ :monthly,
287
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
288
+ )
289
+ YEARLY =
290
+ T.let(
291
+ :yearly,
292
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
293
+ )
294
+ ONE_TIME =
295
+ T.let(
296
+ :one_time,
297
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
298
+ )
299
+ USAGE_BASED =
300
+ T.let(
301
+ :usage_based,
302
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
303
+ )
304
+
305
+ sig do
306
+ override.returns(
307
+ T::Array[
308
+ BrandDev::Models::BrandAIProductResponse::Product::BillingFrequency::TaggedSymbol
309
+ ]
310
+ )
311
+ end
312
+ def self.values
313
+ end
314
+ end
315
+
316
+ # Pricing model for the product
317
+ module PricingModel
318
+ extend BrandDev::Internal::Type::Enum
319
+
320
+ TaggedSymbol =
321
+ T.type_alias do
322
+ T.all(
323
+ Symbol,
324
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel
325
+ )
326
+ end
327
+ OrSymbol = T.type_alias { T.any(Symbol, String) }
328
+
329
+ PER_SEAT =
330
+ T.let(
331
+ :per_seat,
332
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
333
+ )
334
+ FLAT =
335
+ T.let(
336
+ :flat,
337
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
338
+ )
339
+ TIERED =
340
+ T.let(
341
+ :tiered,
342
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
343
+ )
344
+ FREEMIUM =
345
+ T.let(
346
+ :freemium,
347
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
348
+ )
349
+ CUSTOM =
350
+ T.let(
351
+ :custom,
352
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
353
+ )
354
+
355
+ sig do
356
+ override.returns(
357
+ T::Array[
358
+ BrandDev::Models::BrandAIProductResponse::Product::PricingModel::TaggedSymbol
359
+ ]
360
+ )
361
+ end
362
+ def self.values
363
+ end
364
+ end
365
+ end
366
+ end
367
+ end
368
+ end
@@ -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,144 @@
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
+ name: String,
49
+ tags: ::Array[String],
50
+ target_audience: ::Array[String],
51
+ billing_frequency: BrandDev::Models::BrandAIProductResponse::Product::billing_frequency?,
52
+ category: String?,
53
+ currency: String?,
54
+ image_url: String?,
55
+ price: Float?,
56
+ pricing_model: BrandDev::Models::BrandAIProductResponse::Product::pricing_model?,
57
+ url: String?
58
+ }
59
+
60
+ class Product < BrandDev::Internal::Type::BaseModel
61
+ attr_accessor description: String
62
+
63
+ attr_accessor features: ::Array[String]
64
+
65
+ attr_accessor name: String
66
+
67
+ attr_accessor tags: ::Array[String]
68
+
69
+ attr_accessor target_audience: ::Array[String]
70
+
71
+ attr_accessor billing_frequency: BrandDev::Models::BrandAIProductResponse::Product::billing_frequency?
72
+
73
+ attr_accessor category: String?
74
+
75
+ attr_accessor currency: String?
76
+
77
+ attr_accessor image_url: String?
78
+
79
+ attr_accessor price: Float?
80
+
81
+ attr_accessor pricing_model: BrandDev::Models::BrandAIProductResponse::Product::pricing_model?
82
+
83
+ attr_accessor url: String?
84
+
85
+ def initialize: (
86
+ description: String,
87
+ features: ::Array[String],
88
+ name: String,
89
+ tags: ::Array[String],
90
+ target_audience: ::Array[String],
91
+ ?billing_frequency: BrandDev::Models::BrandAIProductResponse::Product::billing_frequency?,
92
+ ?category: String?,
93
+ ?currency: String?,
94
+ ?image_url: String?,
95
+ ?price: Float?,
96
+ ?pricing_model: BrandDev::Models::BrandAIProductResponse::Product::pricing_model?,
97
+ ?url: String?
98
+ ) -> void
99
+
100
+ def to_hash: -> {
101
+ description: String,
102
+ features: ::Array[String],
103
+ name: String,
104
+ tags: ::Array[String],
105
+ target_audience: ::Array[String],
106
+ billing_frequency: BrandDev::Models::BrandAIProductResponse::Product::billing_frequency?,
107
+ category: String?,
108
+ currency: String?,
109
+ image_url: String?,
110
+ price: Float?,
111
+ pricing_model: BrandDev::Models::BrandAIProductResponse::Product::pricing_model?,
112
+ url: String?
113
+ }
114
+
115
+ type billing_frequency = :monthly | :yearly | :one_time | :usage_based
116
+
117
+ module BillingFrequency
118
+ extend BrandDev::Internal::Type::Enum
119
+
120
+ MONTHLY: :monthly
121
+ YEARLY: :yearly
122
+ ONE_TIME: :one_time
123
+ USAGE_BASED: :usage_based
124
+
125
+ def self?.values: -> ::Array[BrandDev::Models::BrandAIProductResponse::Product::billing_frequency]
126
+ end
127
+
128
+ type pricing_model = :per_seat | :flat | :tiered | :freemium | :custom
129
+
130
+ module PricingModel
131
+ extend BrandDev::Internal::Type::Enum
132
+
133
+ PER_SEAT: :per_seat
134
+ FLAT: :flat
135
+ TIERED: :tiered
136
+ FREEMIUM: :freemium
137
+ CUSTOM: :custom
138
+
139
+ def self?.values: -> ::Array[BrandDev::Models::BrandAIProductResponse::Product::pricing_model]
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -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.24.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-09 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