Repository: captaincontrat/hubspot-api-ruby
Pull request #29: Update owners API to v3
Author: login: kpgdev
Created: 2025-03-04T17:38:38Z | Merged: 2025-03-07T09:00:34Z

I've updated with the new structure. A few things to note:

* only made changes to the owners API - not gone near connection.rb
* The values of the ownerId field in v2 are the same as the id field in v3
* the response payload is dramatically different between v2 and v3
* tested locally and works.
* not added any VCR tests in


Diff:
diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml
index c2ba95b2..cfed665a 100644
--- a/.github/workflows/actions.yml
+++ b/.github/workflows/actions.yml
@@ -1,5 +1,5 @@
 name: tests
-on: push
+on: [push, pull_request_target]
 jobs:
   test:
     runs-on: ubuntu-latest
diff --git a/History.md b/History.md
index 2332310e..e1060050 100644
--- a/History.md
+++ b/History.md
@@ -1,3 +1,9 @@
+## 0.20.0
+
+* BREAKING CHANGE for Owner: use v3 API endpoint as v2 will be stopped in a few days.
+  * It changes the return format of Hubspot::Owner.all as it introduces pagination.
+  * fixes #28 - PR #29, thanks @kpgdev!
+
 ## 0.19.0
 
 * Add Task#search endpoint
diff --git a/hubspot-api-ruby.gemspec b/hubspot-api-ruby.gemspec
index 44843ea0..c6086981 100644
--- a/hubspot-api-ruby.gemspec
+++ b/hubspot-api-ruby.gemspec
@@ -1,6 +1,6 @@
 Gem::Specification.new do |s|
   s.name = "hubspot-api-ruby"
-  s.version = "0.19.0"
+  s.version = "0.20.0"
   s.require_paths = ["lib"]
   s.authors = ["Jonathan"]
   s.email = ["jonathan@hoggo.com"]
diff --git a/lib/hubspot/owner.rb b/lib/hubspot/owner.rb
index 18778148..61fd2e65 100644
--- a/lib/hubspot/owner.rb
+++ b/lib/hubspot/owner.rb
@@ -2,24 +2,21 @@ module Hubspot
   #
   # HubSpot Owners API
   #
-  # {http://developers.hubspot.com/docs/methods/owners/get_owners}
+  # {https://developers.hubspot.com/docs/reference/api/crm/owners/v3}
+  #
   #
-  # TODO: Create an Owner
-  # TODO: Update an Owner
-  # TODO: Delete an Owner
   class Owner
-    GET_OWNER_PATH    = '/owners/v2/owners/:owner_id' # GET
-    GET_OWNERS_PATH   = '/owners/v2/owners' # GET
-    CREATE_OWNER_PATH = '/owners/v2/owners' # POST
-    UPDATE_OWNER_PATH = '/owners/v2/owners/:owner_id' # PUT
-    DELETE_OWNER_PATH = '/owners/v2/owners/:owner_id' # DELETE
-
+    GET_OWNER_PATH    = '/crm/v3/owners/:owner_id' # GET
+    GET_OWNERS_PATH   = '/crm/v3/owners' # GET
+    CREATE_OWNER_PATH = "/crm/v3/owners" # POST
+    UPDATE_OWNER_PATH = '/crm/v3/owners/:owner_id' # PUT
+    DELETE_OWNER_PATH = '/crm/v3/owners/:owner_id' # DELETE
 
     attr_reader :properties, :owner_id, :email
 
     def initialize(property_hash)
       @properties = property_hash
-      @owner_id   = @properties['ownerId']
+      @owner_id   = @properties['id']
       @email      = @properties['email']
     end
 
@@ -28,29 +25,46 @@ def [](property)
     end
 
     class << self
-      def all(include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { includeInactive: include_inactive }
+      def all(include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
+
         response = Hubspot::Connection.get_json(path, params)
-        response.map { |r| new(r) }
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find(id, include_inactive=false)
-        path     = GET_OWNER_PATH
-        response = Hubspot::Connection.get_json(path, owner_id: id,
-          include_inactive: include_inactive)
+      def find(id, id_property: nil)
+        path = GET_OWNER_PATH
+        params = { owner_id: id }
+        params[:idProperty] = id_property if id_property
+        response = Hubspot::Connection.get_json(path, params)
         new(response)
       end
 
-      def find_by_email(email, include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { email: email, includeInactive: include_inactive }
+      def find_by_email(email, include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          email: email,
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
         response = Hubspot::Connection.get_json(path, params)
-        response.blank? ? nil : new(response.first)
+        response['results'].blank? ? nil : new(response['results'].first)
       end
 
-      def find_by_emails(emails, include_inactive=false)
-        emails.map { |email| find_by_email(email, include_inactive) }.reject(&:blank?)
+      def find_by_emails(emails = [], include_archived: false)
+        emails.map { |email| find_by_email(email, include_archived: include_archived) }.reject(&:nil?)
       end
     end
   end
diff --git a/spec/fixtures/vcr_cassettes/owner_all.yml b/spec/fixtures/vcr_cassettes/owner_all.yml
index 84a50c49..c132534c 100644
--- a/spec/fixtures/vcr_cassettes/owner_all.yml
+++ b/spec/fixtures/vcr_cassettes/owner_all.yml
@@ -2,7 +2,7 @@
 http_interactions:
 - request:
     method: get
-    uri: https://api.hubapi.com/owners/v2/owners?includeInactive=false
+    uri: https://api.hubapi.com/crm/v3/owners?archived=false&limit=100
     body:
       encoding: US-ASCII
       string: ''
@@ -21,54 +21,53 @@ http_interactions:
       message: OK
     headers:
       Date:
-      - Mon, 08 Aug 2022 14:52:26 GMT
+      - Wed, 05 Mar 2025 11:38:17 GMT
       Content-Type:
       - application/json;charset=utf-8
       Content-Length:
-      - '515'
+      - '1866'
       Connection:
       - keep-alive
       Cf-Ray:
-      - 73791365ffe3399f-CDG
+      - 91b9538109b152be-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Vary:
-      - Accept-Encoding
-      Cf-Cache-Status:
-      - DYNAMIC
+      - origin, Accept-Encoding
       Access-Control-Allow-Credentials:
       - 'false'
-      Expect-Ct:
-      - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
+      X-Content-Type-Options:
+      - nosniff
       X-Hubspot-Correlation-Id:
-      - 747e7630-d002-48f5-ad46-35af910910ff
+      - 9331c70a-9379-4edc-9bc4-b84190dc9720
       X-Hubspot-Ratelimit-Daily:
       - '250000'
       X-Hubspot-Ratelimit-Daily-Remaining:
-      - '248140'
+      - '249983'
       X-Hubspot-Ratelimit-Interval-Milliseconds:
       - '10000'
       X-Hubspot-Ratelimit-Max:
       - '100'
       X-Hubspot-Ratelimit-Remaining:
-      - '80'
+      - '99'
       X-Hubspot-Ratelimit-Secondly:
       - '10'
       X-Hubspot-Ratelimit-Secondly-Remaining:
-      - '8'
-      X-Trace:
-      - 2BA0478645562479771D4E7BB83246C626972536A5000000000000000000
+      - '9'
+      Set-Cookie:
+      - __cf_bm=0dt9BhjcpXf4jM_i9yd8L14OB75bI50nu6afyyHQfag-1741174697-1.0.1.1-MeKKz.oM2eG8DIreiq9AvsdZ_xVmK9_J0pon4E9hh6Z4DmsjJIKW0oMV.zfaaGxH7xiWjHCBJDCEIQ2NrVhPAZG37YLSzZhD7QlbcQHa528;
+        path=/; expires=Wed, 05-Mar-25 12:08:17 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
       Report-To:
-      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=fEVxaJTo5af4tWJAFgx%2Ff4h%2FfZaevI5mfJdZhWDhYM4ewI4WNDSRbSb%2BQy30RYluhyDGamwrwhVx6hqcd5irigHV0BsNEEDNMV4OgrRGArL8EfgMfPuRwshjTStBOSkZrQ92jeH5t3akx6r3"}],"group":"cf-nel","max_age":604800}'
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=G%2FaqcW6F9TBTxRfTJoKlN2QjxlZWP0PRTybYpHzzf5gZELhznuR8GJhY7y0jl76ywF5Y9oy34uVAA3lYgdes4azoQVg9KE4piyWuA7Umvd8yehMxMJ%2BJNQxad9tldmTeRY7t2UOMgR5vrx3k"}],"group":"cf-nel","max_age":604800}'
       Nel:
       - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
       Server:
       - cloudflare
-      Alt-Svc:
-      - h3=":443"; ma=86400, h3-29=":443"; ma=86400
     body:
       encoding: ASCII-8BIT
-      string: !binary |-
-        W3sicG9ydGFsSWQiOjxQT1JUQUxfSUQ+LCJvd25lcklkIjoxNTY2NDQzODYsInR5cGUiOiJQRVJTT04iLCJmaXJzdE5hbWUiOiJBdWd1c3RpbiIsImxhc3ROYW1lIjoiZGUgTWFpbnRlbmFudCIsImVtYWlsIjoiYXVndXN0aW5AY2FwdGFpbmNvbnRyYXQuY29tIiwiY3JlYXRlZEF0IjoxNjQ2OTAxMzA3NTAwLCJ1cGRhdGVkQXQiOjE2NTIwODIwODA0NTIsInJlbW90ZUxpc3QiOlt7ImlkIjoxMTUzNTM3MjcsInBvcnRhbElkIjo8UE9SVEFMX0lEPiwib3duZXJJZCI6MTU2NjQ0Mzg2LCJyZW1vdGVJZCI6IjExNTk4Njk0IiwicmVtb3RlVHlwZSI6IkhVQlNQT1QiLCJhY3RpdmUiOnRydWV9XSwiaGFzQ29udGFjdHNBY2Nlc3MiOmZhbHNlLCJhY3RpdmVTYWxlc2ZvcmNlSWQiOm51bGwsInVzZXJJZEluY2x1ZGluZ0luYWN0aXZlIjoxMTU5ODY5NCwiYWN0aXZlVXNlcklkIjoxMTU5ODY5NCwiaXNBY3RpdmUiOnRydWV9LHsicG9ydGFsSWQiOjxQT1JUQUxfSUQ+LCJvd25lcklkIjoxNTgxMzc0OTAsInR5cGUiOiJQRVJTT04iLCJmaXJzdE5hbWUiOiJCb3JpcyIsImxhc3ROYW1lIjoiQWxmw7ZsZGkiLCJlbWFpbCI6ImJvcmlzQGNhcHRhaW5jb250cmF0LmNvbSIsImNyZWF0ZWRBdCI6MTY0NzI3NzMwNDAzMCwidXBkYXRlZEF0IjoxNjU5MDk1NzU2Mzc0LCJyZW1vdGVMaXN0IjpbeyJpZCI6MTE1OTk3MzY1LCJwb3J0YWxJZCI6PFBPUlRBTF9JRD4sIm93bmVySWQiOjE1ODEzNzQ5MCwicmVtb3RlSWQiOiIyNzg2MTkwMSIsInJlbW90ZVR5cGUiOiJIVUJTUE9UIiwiYWN0aXZlIjp0cnVlfV0sImhhc0NvbnRhY3RzQWNjZXNzIjpmYWxzZSwiYWN0aXZlU2FsZXNmb3JjZUlkIjpudWxsLCJ1c2VySWRJbmNsdWRpbmdJbmFjdGl2ZSI6Mjc4NjE5MDEsImFjdGl2ZVVzZXJJZCI6Mjc4NjE5MDEsImlzQWN0aXZlIjp0cnVlfSx7InBvcnRhbElkIjo8UE9SVEFMX0lEPiwib3duZXJJZCI6MTU2NjQ0Mzg3LCJ0eXBlIjoiUEVSU09OIiwiZmlyc3ROYW1lIjoiTWFub24iLCJsYXN0TmFtZSI6IlByZXZvdCIsImVtYWlsIjoibWFub25AY2FwdGFpbmNvbnRyYXQuY29tIiwiY3JlYXRlZEF0IjoxNjQ2OTAxMzA3NTUwLCJ1cGRhdGVkQXQiOjE2NTE0OTM1NTE2MTksInJlbW90ZUxpc3QiOlt7ImlkIjoxMTUzNTM3MjgsInBvcnRhbElkIjo8UE9SVEFMX0lEPiwib3duZXJJZCI6MTU2NjQ0Mzg3LCJyZW1vdGVJZCI6IjM5MDU5NTUiLCJyZW1vdGVUeXBlIjoiSFVCU1BPVCIsImFjdGl2ZSI6dHJ1ZX1dLCJoYXNDb250YWN0c0FjY2VzcyI6ZmFsc2UsImFjdGl2ZVNhbGVzZm9yY2VJZCI6bnVsbCwidXNlcklkSW5jbHVkaW5nSW5hY3RpdmUiOjM5MDU5NTUsImFjdGl2ZVVzZXJJZCI6MzkwNTk1NSwiaXNBY3RpdmUiOnRydWV9LHsicG9ydGFsSWQiOjxQT1JUQUxfSUQ+LCJvd25lcklkIjo4ODM1NDE2MCwidHlwZSI6IlBFUlNPTiIsImZpcnN0TmFtZSI6Illhbm5pY2siLCJsYXN0TmFtZSI6IkZvbmphbGxheiIsImVtYWlsIjoieWFubmlja0BjYXB0YWluY29udHJhdC5jb20iLCJjcmVhdGVkQXQiOjE2MjU0ODkyODQ2NjksInVwZGF0ZWRBdCI6MTYzMjQwNTUyMzI4OCwicmVtb3RlTGlzdCI6W3siaWQiOjU1OTY1MTA1LCJwb3J0YWxJZCI6PFBPUlRBTF9JRD4sIm93bmVySWQiOjg4MzU0MTYwLCJyZW1vdGVJZCI6IjMzMjYwMzgiLCJyZW1vdGVUeXBlIjoiSFVCU1BPVCIsImFjdGl2ZSI6dHJ1ZX1dLCJoYXNDb250YWN0c0FjY2VzcyI6ZmFsc2UsImFjdGl2ZVNhbGVzZm9yY2VJZCI6bnVsbCwidXNlcklkSW5jbHVkaW5nSW5hY3RpdmUiOjMzMjYwMzgsImFjdGl2ZVVzZXJJZCI6MzMyNjAzOCwiaXNBY3RpdmUiOnRydWV9XQ==
-  recorded_at: Mon, 08 Aug 2022 14:52:26 GMT
-recorded_with: VCR 6.0.0
+      string: '{"results":[{"id":"31871817","email":"p[redacted]e@captaincontrat.com","type":"PERSON","firstName":"Philippe","lastName":"W[redacted]","userId":2506672,"userIdIncludingInactive":2506672,"createdAt":"2018-04-09T13:16:56.625Z","updatedAt":"2018-04-09T13:16:56.625Z","archived":false},{"id":"31871900","email":"p[redacted]s@captaincontrat.com","type":"PERSON","firstName":"Paul-Yves","lastName":"L[redacted]","userId":5555888,"userIdIncludingInactive":5555888,"createdAt":"2018-04-09T13:39:06.662Z","updatedAt":"2022-04-27T12:44:02.847Z","archived":false},{"id":"31872455","email":"y[redacted]k@captaincontrat.com","type":"PERSON","firstName":"Yannick","lastName":"F[redacted]","userId":3326038,"userIdIncludingInactive":3326038,"createdAt":"2018-04-09T13:18:57.349Z","updatedAt":"2021-09-23T13:58:43.251Z","archived":false},{"id":"414566270","email":"g[redacted]c@captaincontrat.com","type":"PERSON","firstName":"Guillaume","lastName":"C[redacted]","userId":51647443,"userIdIncludingInactive":51647443,"createdAt":"2023-05-22T13:08:58.190Z","updatedAt":"2023-06-20T13:05:15.163Z","archived":false},{"id":"426301584","email":"n[redacted]d@captaincontrat.com","type":"PERSON","firstName":"Nicolas","lastName":"D[redacted]","userId":51867598,"userIdIncludingInactive":51867598,"createdAt":"2023-06-02T10:47:32.680Z","updatedAt":"2025-03-04T08:35:29.226Z","archived":false},{"id":"542504584","email":"p[redacted]d@captaincontrat.com","type":"PERSON","firstName":"Pierre","lastName":"N[redacted]","userId":60546148,"userIdIncludingInactive":60546148,"createdAt":"2023-09-18T08:46:35.653Z","updatedAt":"2025-02-26T13:09:06.739Z","archived":false},{"id":"691403032","email":"a[redacted]e@captaincontrat.com","type":"PERSON","firstName":"Ayoub","lastName":"E[redacted]","userId":63169306,"userIdIncludingInactive":63169306,"createdAt":"2024-01-17T11:24:32.528Z","updatedAt":"2024-03-01T13:46:28.109Z","archived":false}]}'
+  recorded_at: Wed, 05 Mar 2025 11:38:17 GMT
+recorded_with: VCR 6.3.1
diff --git a/spec/fixtures/vcr_cassettes/owner_example.yml b/spec/fixtures/vcr_cassettes/owner_example.yml
index 8d36a357..a0417683 100644
--- a/spec/fixtures/vcr_cassettes/owner_example.yml
+++ b/spec/fixtures/vcr_cassettes/owner_example.yml
@@ -2,7 +2,7 @@
 http_interactions:
 - request:
     method: get
-    uri: https://api.hubapi.com/owners/v2/owners
+    uri: https://api.hubapi.com/crm/v3/owners
     body:
       encoding: US-ASCII
       string: ''
@@ -21,54 +21,53 @@ http_interactions:
       message: OK
     headers:
       Date:
-      - Mon, 08 Aug 2022 14:52:27 GMT
+      - Wed, 05 Mar 2025 11:38:17 GMT
       Content-Type:
       - application/json;charset=utf-8
       Content-Length:
-      - '515'
+      - '1866'
       Connection:
       - keep-alive
       Cf-Ray:
-      - 7379137168603a5d-CDG
+      - 91b953833cf9024b-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Vary:
-      - Accept-Encoding
-      Cf-Cache-Status:
-      - DYNAMIC
+      - origin, accept-encoding
       Access-Control-Allow-Credentials:
       - 'false'
-      Expect-Ct:
-      - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
+      X-Content-Type-Options:
+      - nosniff
       X-Hubspot-Correlation-Id:
-      - e57f9a8d-3d59-4cb6-af9b-42e4e1a0e50d
+      - 17d80648-852b-4b5b-a491-e90786ca356d
       X-Hubspot-Ratelimit-Daily:
       - '250000'
       X-Hubspot-Ratelimit-Daily-Remaining:
-      - '248136'
+      - '249982'
       X-Hubspot-Ratelimit-Interval-Milliseconds:
       - '10000'
       X-Hubspot-Ratelimit-Max:
       - '100'
       X-Hubspot-Ratelimit-Remaining:
-      - '77'
+      - '98'
       X-Hubspot-Ratelimit-Secondly:
       - '10'
       X-Hubspot-Ratelimit-Secondly-Remaining:
-      - '7'
-      X-Trace:
-      - 2B1FBA67FD57C6E548303BAA0F54ABC17C570D786D000000000000000000
+      - '9'
+      Set-Cookie:
+      - __cf_bm=YK3ZCjIcxPdQZce1SrY1eFEZMIYiNZ7oHltUf8QieNs-1741174697-1.0.1.1-.0XmR3pETUcTuIFHSel1xAoNIjBlNqS3wgbGQr8YPJ.94VddYKrYJhq5sFflefsYb9FRMR7qnxlfEp0CCNujYx1dJetSL7TYZzCg_dzX0ZE;
+        path=/; expires=Wed, 05-Mar-25 12:08:17 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
       Report-To:
-      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=xYGc%2B1M0pQNRD93UYX%2FoaLpLtqVPYUzC%2FiMN6%2FDAKNHk2NTxvRVpZ7l74JK5b3isHqazlz0gw%2FOFMElyOOoUSiv9GI84RmpII0062o2dF%2FsWelCj%2FXbrtbVvKZMmleTLJnY4UT%2Bcti9pTeDk"}],"group":"cf-nel","max_age":604800}'
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=IQhqag5DuChPWKe9aPkNKRQHXZim%2BXKRGj3Fql1CqrBqnyJJFaCbe16n8IM0ZBumN%2BMdmCM09bAwcsQmA%2FvR6uQYOKp1Khv2Zt8fPg8TiP7LkzKhUnO07HLc0pDqCUsJEUvfQfEBs9Avn%2FJZ"}],"group":"cf-nel","max_age":604800}'
       Nel:
       - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
       Server:
       - cloudflare
-      Alt-Svc:
-      - h3=":443"; ma=86400, h3-29=":443"; ma=86400
     body:
       encoding: ASCII-8BIT
-      string: !binary |-
-        W3sicG9ydGFsSWQiOjxQT1JUQUxfSUQ+LCJvd25lcklkIjoxNTY2NDQzODYsInR5cGUiOiJQRVJTT04iLCJmaXJzdE5hbWUiOiJBdWd1c3RpbiIsImxhc3ROYW1lIjoiZGUgTWFpbnRlbmFudCIsImVtYWlsIjoiYXVndXN0aW5AY2FwdGFpbmNvbnRyYXQuY29tIiwiY3JlYXRlZEF0IjoxNjQ2OTAxMzA3NTAwLCJ1cGRhdGVkQXQiOjE2NTIwODIwODA0NTIsInJlbW90ZUxpc3QiOlt7ImlkIjoxMTUzNTM3MjcsInBvcnRhbElkIjo8UE9SVEFMX0lEPiwib3duZXJJZCI6MTU2NjQ0Mzg2LCJyZW1vdGVJZCI6IjExNTk4Njk0IiwicmVtb3RlVHlwZSI6IkhVQlNQT1QiLCJhY3RpdmUiOnRydWV9XSwiaGFzQ29udGFjdHNBY2Nlc3MiOmZhbHNlLCJhY3RpdmVTYWxlc2ZvcmNlSWQiOm51bGwsInVzZXJJZEluY2x1ZGluZ0luYWN0aXZlIjoxMTU5ODY5NCwiYWN0aXZlVXNlcklkIjoxMTU5ODY5NCwiaXNBY3RpdmUiOnRydWV9LHsicG9ydGFsSWQiOjxQT1JUQUxfSUQ+LCJvd25lcklkIjoxNTgxMzc0OTAsInR5cGUiOiJQRVJTT04iLCJmaXJzdE5hbWUiOiJCb3JpcyIsImxhc3ROYW1lIjoiQWxmw7ZsZGkiLCJlbWFpbCI6ImJvcmlzQGNhcHRhaW5jb250cmF0LmNvbSIsImNyZWF0ZWRBdCI6MTY0NzI3NzMwNDAzMCwidXBkYXRlZEF0IjoxNjU5MDk1NzU2Mzc0LCJyZW1vdGVMaXN0IjpbeyJpZCI6MTE1OTk3MzY1LCJwb3J0YWxJZCI6PFBPUlRBTF9JRD4sIm93bmVySWQiOjE1ODEzNzQ5MCwicmVtb3RlSWQiOiIyNzg2MTkwMSIsInJlbW90ZVR5cGUiOiJIVUJTUE9UIiwiYWN0aXZlIjp0cnVlfV0sImhhc0NvbnRhY3RzQWNjZXNzIjpmYWxzZSwiYWN0aXZlU2FsZXNmb3JjZUlkIjpudWxsLCJ1c2VySWRJbmNsdWRpbmdJbmFjdGl2ZSI6Mjc4NjE5MDEsImFjdGl2ZVVzZXJJZCI6Mjc4NjE5MDEsImlzQWN0aXZlIjp0cnVlfSx7InBvcnRhbElkIjo8UE9SVEFMX0lEPiwib3duZXJJZCI6MTU2NjQ0Mzg3LCJ0eXBlIjoiUEVSU09OIiwiZmlyc3ROYW1lIjoiTWFub24iLCJsYXN0TmFtZSI6IlByZXZvdCIsImVtYWlsIjoibWFub25AY2FwdGFpbmNvbnRyYXQuY29tIiwiY3JlYXRlZEF0IjoxNjQ2OTAxMzA3NTUwLCJ1cGRhdGVkQXQiOjE2NTE0OTM1NTE2MTksInJlbW90ZUxpc3QiOlt7ImlkIjoxMTUzNTM3MjgsInBvcnRhbElkIjo8UE9SVEFMX0lEPiwib3duZXJJZCI6MTU2NjQ0Mzg3LCJyZW1vdGVJZCI6IjM5MDU5NTUiLCJyZW1vdGVUeXBlIjoiSFVCU1BPVCIsImFjdGl2ZSI6dHJ1ZX1dLCJoYXNDb250YWN0c0FjY2VzcyI6ZmFsc2UsImFjdGl2ZVNhbGVzZm9yY2VJZCI6bnVsbCwidXNlcklkSW5jbHVkaW5nSW5hY3RpdmUiOjM5MDU5NTUsImFjdGl2ZVVzZXJJZCI6MzkwNTk1NSwiaXNBY3RpdmUiOnRydWV9LHsicG9ydGFsSWQiOjxQT1JUQUxfSUQ+LCJvd25lcklkIjo4ODM1NDE2MCwidHlwZSI6IlBFUlNPTiIsImZpcnN0TmFtZSI6Illhbm5pY2siLCJsYXN0TmFtZSI6IkZvbmphbGxheiIsImVtYWlsIjoieWFubmlja0BjYXB0YWluY29udHJhdC5jb20iLCJjcmVhdGVkQXQiOjE2MjU0ODkyODQ2NjksInVwZGF0ZWRBdCI6MTYzMjQwNTUyMzI4OCwicmVtb3RlTGlzdCI6W3siaWQiOjU1OTY1MTA1LCJwb3J0YWxJZCI6PFBPUlRBTF9JRD4sIm93bmVySWQiOjg4MzU0MTYwLCJyZW1vdGVJZCI6IjMzMjYwMzgiLCJyZW1vdGVUeXBlIjoiSFVCU1BPVCIsImFjdGl2ZSI6dHJ1ZX1dLCJoYXNDb250YWN0c0FjY2VzcyI6ZmFsc2UsImFjdGl2ZVNhbGVzZm9yY2VJZCI6bnVsbCwidXNlcklkSW5jbHVkaW5nSW5hY3RpdmUiOjMzMjYwMzgsImFjdGl2ZVVzZXJJZCI6MzMyNjAzOCwiaXNBY3RpdmUiOnRydWV9XQ==
-  recorded_at: Mon, 08 Aug 2022 14:52:27 GMT
-recorded_with: VCR 6.0.0
+      string: '{"results":[{"id":"31871817","email":"p[redacted]e@captaincontrat.com","type":"PERSON","firstName":"Philippe","lastName":"W[redacted]","userId":2506672,"userIdIncludingInactive":2506672,"createdAt":"2018-04-09T13:16:56.625Z","updatedAt":"2018-04-09T13:16:56.625Z","archived":false},{"id":"31871900","email":"p[redacted]s@captaincontrat.com","type":"PERSON","firstName":"Paul-Yves","lastName":"L[redacted]","userId":5555888,"userIdIncludingInactive":5555888,"createdAt":"2018-04-09T13:39:06.662Z","updatedAt":"2022-04-27T12:44:02.847Z","archived":false},{"id":"31872455","email":"y[redacted]k@captaincontrat.com","type":"PERSON","firstName":"Yannick","lastName":"F[redacted]","userId":3326038,"userIdIncludingInactive":3326038,"createdAt":"2018-04-09T13:18:57.349Z","updatedAt":"2021-09-23T13:58:43.251Z","archived":false},{"id":"414566270","email":"g[redacted]c@captaincontrat.com","type":"PERSON","firstName":"Guillaume","lastName":"C[redacted]","userId":51647443,"userIdIncludingInactive":51647443,"createdAt":"2023-05-22T13:08:58.190Z","updatedAt":"2023-06-20T13:05:15.163Z","archived":false},{"id":"426301584","email":"n[redacted]d@captaincontrat.com","type":"PERSON","firstName":"Nicolas","lastName":"D[redacted]","userId":51867598,"userIdIncludingInactive":51867598,"createdAt":"2023-06-02T10:47:32.680Z","updatedAt":"2025-03-04T08:35:29.226Z","archived":false},{"id":"542504584","email":"p[redacted]d@captaincontrat.com","type":"PERSON","firstName":"Pierre","lastName":"N[redacted]","userId":60546148,"userIdIncludingInactive":60546148,"createdAt":"2023-09-18T08:46:35.653Z","updatedAt":"2025-02-26T13:09:06.739Z","archived":false},{"id":"691403032","email":"a[redacted]e@captaincontrat.com","type":"PERSON","firstName":"Ayoub","lastName":"E[redacted]","userId":63169306,"userIdIncludingInactive":63169306,"createdAt":"2024-01-17T11:24:32.528Z","updatedAt":"2024-03-01T13:46:28.109Z","archived":false}]}'
+  recorded_at: Wed, 05 Mar 2025 11:38:17 GMT
+recorded_with: VCR 6.3.1
diff --git a/spec/fixtures/vcr_cassettes/owner_find_by_email.yml b/spec/fixtures/vcr_cassettes/owner_find_by_email.yml
index 89ff7757..6d254878 100644
--- a/spec/fixtures/vcr_cassettes/owner_find_by_email.yml
+++ b/spec/fixtures/vcr_cassettes/owner_find_by_email.yml
@@ -2,7 +2,7 @@
 http_interactions:
 - request:
     method: get
-    uri: https://api.hubapi.com/owners/v2/owners?email=augustin@captaincontrat.com&includeInactive=false
+    uri: https://api.hubapi.com/crm/v3/owners?archived=false&email=p%5Bredacted%5De@captaincontrat.com&limit=100
     body:
       encoding: US-ASCII
       string: ''
@@ -21,54 +21,53 @@ http_interactions:
       message: OK
     headers:
       Date:
-      - Mon, 08 Aug 2022 14:52:27 GMT
+      - Wed, 05 Mar 2025 11:38:28 GMT
       Content-Type:
       - application/json;charset=utf-8
       Content-Length:
-      - '292'
+      - '274'
       Connection:
       - keep-alive
       Cf-Ray:
-      - 7379136b78e132ad-CDG
+      - 91b953c6cc6b6f11-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Vary:
-      - Accept-Encoding
-      Cf-Cache-Status:
-      - DYNAMIC
+      - origin, accept-encoding
       Access-Control-Allow-Credentials:
       - 'false'
-      Expect-Ct:
-      - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
+      X-Content-Type-Options:
+      - nosniff
       X-Hubspot-Correlation-Id:
-      - 24df9681-ea0a-4385-a9fd-abfd14ab08e5
+      - 4edb687b-16ff-4f22-a66b-1413341741c5
       X-Hubspot-Ratelimit-Daily:
       - '250000'
       X-Hubspot-Ratelimit-Daily-Remaining:
-      - '248137'
+      - '249981'
       X-Hubspot-Ratelimit-Interval-Milliseconds:
       - '10000'
       X-Hubspot-Ratelimit-Max:
       - '100'
       X-Hubspot-Ratelimit-Remaining:
-      - '78'
+      - '99'
       X-Hubspot-Ratelimit-Secondly:
       - '10'
       X-Hubspot-Ratelimit-Secondly-Remaining:
-      - '7'
-      X-Trace:
-      - 2B9EF51CD72C818098D751540FB365C2DDEAEEB68F000000000000000000
+      - '9'
+      Set-Cookie:
+      - __cf_bm=5aEpvjgN9tVWwOkVXhJWBBtLEZNJ9HDW5pjZFV2Cpx4-1741174708-1.0.1.1-_7BDg28sHMQCu4cZJwfMQK1uPpRZifN_LpijKxjX8WH4F0u8siorko.n1Gj4tkqj5DLBinySVIidStdjiEeXfPQp9XaPcugWcaJaeJIeBVw;
+        path=/; expires=Wed, 05-Mar-25 12:08:28 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
       Report-To:
-      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=brrPsL2e3DBYura6eChcckSCnhDzuO%2FVX6%2FZI2lBgvMLFVHEpwEQ5A6YYV%2Bi1g7VjK7ylUZWK0vaWjIsKGN11K2DCrQDaWR4oQZ5AfloI6sHVFOUIi4mZrkgFEqqCq3eCYJU6Yllwp94v%2Fep"}],"group":"cf-nel","max_age":604800}'
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=C77HkdghvxM4Ub0dfKy0PxfJu903mmgpq8p0UGha%2BGV%2FAnWSy55EoSTqx1K3j7oOrM2VWSZOIxZUlFi55oBKifO%2FRkMaae4bGkOrR2Act3Vp55Qcz91nd5pRUKPxc805thD1OoCFcKLCEYwz"}],"group":"cf-nel","max_age":604800}'
       Nel:
       - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
       Server:
       - cloudflare
-      Alt-Svc:
-      - h3=":443"; ma=86400, h3-29=":443"; ma=86400
     body:
       encoding: ASCII-8BIT
-      string: '[{"portalId":<PORTAL_ID>,"ownerId":156644386,"type":"PERSON","firstName":"Augustin","lastName":"de
-        Maintenant","email":"augustin@captaincontrat.com","createdAt":1646901307500,"updatedAt":1652082080452,"remoteList":[{"id":115353727,"portalId":<PORTAL_ID>,"ownerId":156644386,"remoteId":"11598694","remoteType":"HUBSPOT","active":true}],"hasContactsAccess":false,"activeSalesforceId":null,"userIdIncludingInactive":11598694,"activeUserId":11598694,"isActive":true}]'
-  recorded_at: Mon, 08 Aug 2022 14:52:27 GMT
-recorded_with: VCR 6.0.0
+      string: '{"results":[{"id":"31871817","email":"p[redacted]e@captaincontrat.com","type":"PERSON","firstName":"Philippe","lastName":"W[redacted]","userId":2506672,"userIdIncludingInactive":2506672,"createdAt":"2018-04-09T13:16:56.625Z","updatedAt":"2018-04-09T13:16:56.625Z","archived":false}]}'
+  recorded_at: Wed, 05 Mar 2025 11:38:29 GMT
+recorded_with: VCR 6.3.1
diff --git a/spec/fixtures/vcr_cassettes/owner_find_by_emails.yml b/spec/fixtures/vcr_cassettes/owner_find_by_emails.yml
index 19980d86..100c1bb8 100644
--- a/spec/fixtures/vcr_cassettes/owner_find_by_emails.yml
+++ b/spec/fixtures/vcr_cassettes/owner_find_by_emails.yml
@@ -2,7 +2,7 @@
 http_interactions:
 - request:
     method: get
-    uri: https://api.hubapi.com/owners/v2/owners?email=augustin@captaincontrat.com&includeInactive=false
+    uri: https://api.hubapi.com/crm/v3/owners?archived=false&email=p%5Bredacted%5De@captaincontrat.com&limit=100
     body:
       encoding: US-ASCII
       string: ''
@@ -21,59 +21,58 @@ http_interactions:
       message: OK
     headers:
       Date:
-      - Mon, 08 Aug 2022 14:52:28 GMT
+      - Wed, 05 Mar 2025 11:38:29 GMT
       Content-Type:
       - application/json;charset=utf-8
       Content-Length:
-      - '292'
+      - '274'
       Connection:
       - keep-alive
       Cf-Ray:
-      - 737913735d073a17-CDG
+      - 91b953ccfbc66fb1-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Vary:
-      - Accept-Encoding
-      Cf-Cache-Status:
-      - DYNAMIC
+      - origin, Accept-Encoding
       Access-Control-Allow-Credentials:
       - 'false'
-      Expect-Ct:
-      - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
+      X-Content-Type-Options:
+      - nosniff
       X-Hubspot-Correlation-Id:
-      - c047d22b-8391-43fe-a48f-1f239d90ae9d
+      - 926bebd5-dcff-4edd-b8c8-02b477bd3bc1
       X-Hubspot-Ratelimit-Daily:
       - '250000'
       X-Hubspot-Ratelimit-Daily-Remaining:
-      - '248135'
+      - '249980'
       X-Hubspot-Ratelimit-Interval-Milliseconds:
       - '10000'
       X-Hubspot-Ratelimit-Max:
       - '100'
       X-Hubspot-Ratelimit-Remaining:
-      - '77'
+      - '98'
       X-Hubspot-Ratelimit-Secondly:
       - '10'
       X-Hubspot-Ratelimit-Secondly-Remaining:
-      - '7'
-      X-Trace:
-      - 2BD79A0F83E1115B568BBF71B747AC7D39C9303B7C000000000000000000
+      - '9'
+      Set-Cookie:
+      - __cf_bm=U.SWgFLYx_wX6RIUjMAbYBEb8L4uyUCFKgQ6IXt5Y2M-1741174709-1.0.1.1-ZGWEpdEBTg2hNiVj2q9E30ogG_iWoRmRcYxF8bRWsV.W0LFFU88mJpxLi9D18k9GZVj4zjN7BJrZiA3MYxAKqo5d3bUA8_gIE.qGGFkLpQY;
+        path=/; expires=Wed, 05-Mar-25 12:08:29 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
       Report-To:
-      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=R3oyCK96U8NKTjHNQ8YROcFUchwS6m5KrfyrQ2NQOwjTWKt0LS6vjQ9Z%2FuiCaPnogc55AOxX60xI7WXO%2Bhma0u1%2BoOZe6ysT4WCEvbxPJ1NOjZx7%2FE2u5kp0xyXJ6XafZdTDnOpDY96Z1hop"}],"group":"cf-nel","max_age":604800}'
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=%2FlOHUT9TXa1BGL%2BuOR9MdThfs3rcgsw59F6QazzaXmtsZXdKo5rCByXaaa6Z6V%2BAvrEG7J%2F%2BDpdO0kDbpIUDjvD2tHZsLDVjPkjGomGwGsN%2FuI8SKcgz2wT3Oep105PcH5oxG31e1AB6JNiA"}],"group":"cf-nel","max_age":604800}'
       Nel:
       - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
       Server:
       - cloudflare
-      Alt-Svc:
-      - h3=":443"; ma=86400, h3-29=":443"; ma=86400
     body:
       encoding: ASCII-8BIT
-      string: '[{"portalId":<PORTAL_ID>,"ownerId":156644386,"type":"PERSON","firstName":"Augustin","lastName":"de
-        Maintenant","email":"augustin@captaincontrat.com","createdAt":1646901307500,"updatedAt":1652082080452,"remoteList":[{"id":115353727,"portalId":<PORTAL_ID>,"ownerId":156644386,"remoteId":"11598694","remoteType":"HUBSPOT","active":true}],"hasContactsAccess":false,"activeSalesforceId":null,"userIdIncludingInactive":11598694,"activeUserId":11598694,"isActive":true}]'
-  recorded_at: Mon, 08 Aug 2022 14:52:28 GMT
+      string: '{"results":[{"id":"31871817","email":"p[redacted]e@captaincontrat.com","type":"PERSON","firstName":"Philippe","lastName":"W[redacted]","userId":2506672,"userIdIncludingInactive":2506672,"createdAt":"2018-04-09T13:16:56.625Z","updatedAt":"2018-04-09T13:16:56.625Z","archived":false}]}'
+  recorded_at: Wed, 05 Mar 2025 11:38:29 GMT
 - request:
     method: get
-    uri: https://api.hubapi.com/owners/v2/owners?email=boris@captaincontrat.com&includeInactive=false
+    uri: https://api.hubapi.com/crm/v3/owners?archived=false&email=p%5Bredacted%5Ds@captaincontrat.com&limit=100
     body:
       encoding: US-ASCII
       string: ''
@@ -92,59 +91,58 @@ http_interactions:
       message: OK
     headers:
       Date:
-      - Mon, 08 Aug 2022 14:52:28 GMT
+      - Wed, 05 Mar 2025 11:38:29 GMT
       Content-Type:
       - application/json;charset=utf-8
       Content-Length:
-      - '290'
+      - '275'
       Connection:
       - keep-alive
       Cf-Ray:
-      - 737913759a690834-CDG
+      - 91b953cdf9cc02b9-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Vary:
-      - Accept-Encoding
-      Cf-Cache-Status:
-      - DYNAMIC
+      - origin, accept-encoding
       Access-Control-Allow-Credentials:
       - 'false'
-      Expect-Ct:
-      - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
+      X-Content-Type-Options:
+      - nosniff
       X-Hubspot-Correlation-Id:
-      - 1acb2001-57e6-46db-89f1-3644a31fc1f6
+      - 77f54090-bc43-4ccc-9695-2be433107998
       X-Hubspot-Ratelimit-Daily:
       - '250000'
       X-Hubspot-Ratelimit-Daily-Remaining:
-      - '248134'
+      - '249979'
       X-Hubspot-Ratelimit-Interval-Milliseconds:
       - '10000'
       X-Hubspot-Ratelimit-Max:
       - '100'
       X-Hubspot-Ratelimit-Remaining:
-      - '76'
+      - '97'
       X-Hubspot-Ratelimit-Secondly:
       - '10'
       X-Hubspot-Ratelimit-Secondly-Remaining:
-      - '7'
-      X-Trace:
-      - 2B52C052578C59FD611F7D61CE073FF6A9EC524121000000000000000000
+      - '9'
+      Set-Cookie:
+      - __cf_bm=.z96KXSvE15GSigufvh8yX572bWm7xNtupST9LrfUg4-1741174709-1.0.1.1-5HymhlGc0JTdq9YKqsXGGg8nHC6jccaTGDNtdOycBxzrQ7cjgco9ucq_yeg88joU8coWOuwZGp34fhJNgIkWyMlICimMw81Siek0jcT0tJU;
+        path=/; expires=Wed, 05-Mar-25 12:08:29 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
       Report-To:
-      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=vWbX2JRxgvCYqzMAml6ZuI6zXhxGQvXdHWG4Xm1wRHktxhi8PzuvfFppbxJue69TrHtZOZUk2UtePKH7b1jIyl8u6L5KgsFlDEOj84JdRJTajKOR5Av8pff8LodKTBErNoNc4SUfW9pgN6%2Fe"}],"group":"cf-nel","max_age":604800}'
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=seGZc0QoPnc0BHNMFuQBBbJ3I%2FpGgbQPQqW6FtCt6sQu5d1ZLmLTmju1VuQW4RIAokqzsMM4aVpiNbLDN6E82wOdzDFSnB2JrCWKwfWN0jU%2FDLOIhFiSLIp8r0tH%2BOZ9IfGYsyZOy7Z44nUO"}],"group":"cf-nel","max_age":604800}'
       Nel:
       - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
       Server:
       - cloudflare
-      Alt-Svc:
-      - h3=":443"; ma=86400, h3-29=":443"; ma=86400
     body:
       encoding: ASCII-8BIT
-      string: !binary |-
-        W3sicG9ydGFsSWQiOjxQT1JUQUxfSUQ+LCJvd25lcklkIjoxNTgxMzc0OTAsInR5cGUiOiJQRVJTT04iLCJmaXJzdE5hbWUiOiJCb3JpcyIsImxhc3ROYW1lIjoiQWxmw7ZsZGkiLCJlbWFpbCI6ImJvcmlzQGNhcHRhaW5jb250cmF0LmNvbSIsImNyZWF0ZWRBdCI6MTY0NzI3NzMwNDAzMCwidXBkYXRlZEF0IjoxNjU5MDk1NzU2Mzc0LCJyZW1vdGVMaXN0IjpbeyJpZCI6MTE1OTk3MzY1LCJwb3J0YWxJZCI6PFBPUlRBTF9JRD4sIm93bmVySWQiOjE1ODEzNzQ5MCwicmVtb3RlSWQiOiIyNzg2MTkwMSIsInJlbW90ZVR5cGUiOiJIVUJTUE9UIiwiYWN0aXZlIjp0cnVlfV0sImhhc0NvbnRhY3RzQWNjZXNzIjpmYWxzZSwiYWN0aXZlU2FsZXNmb3JjZUlkIjpudWxsLCJ1c2VySWRJbmNsdWRpbmdJbmFjdGl2ZSI6Mjc4NjE5MDEsImFjdGl2ZVVzZXJJZCI6Mjc4NjE5MDEsImlzQWN0aXZlIjp0cnVlfV0=
-  recorded_at: Mon, 08 Aug 2022 14:52:28 GMT
+      string: '{"results":[{"id":"31871900","email":"p[redacted]s@captaincontrat.com","type":"PERSON","firstName":"Paul-Yves","lastName":"L[redacted]","userId":5555888,"userIdIncludingInactive":5555888,"createdAt":"2018-04-09T13:39:06.662Z","updatedAt":"2022-04-27T12:44:02.847Z","archived":false}]}'
+  recorded_at: Wed, 05 Mar 2025 11:38:29 GMT
 - request:
     method: get
-    uri: https://api.hubapi.com/owners/v2/owners?email=manon@captaincontrat.com&includeInactive=false
+    uri: https://api.hubapi.com/crm/v3/owners?archived=false&email=y%5Bredacted%5Dk@captaincontrat.com&limit=100
     body:
       encoding: US-ASCII
       string: ''
@@ -163,58 +161,58 @@ http_interactions:
       message: OK
     headers:
       Date:
-      - Mon, 08 Aug 2022 14:52:29 GMT
+      - Wed, 05 Mar 2025 11:38:30 GMT
       Content-Type:
       - application/json;charset=utf-8
       Content-Length:
-      - '283'
+      - '275'
       Connection:
       - keep-alive
       Cf-Ray:
-      - 737913791f493ad1-CDG
+      - 91b953d008da2a67-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Vary:
-      - Accept-Encoding
-      Cf-Cache-Status:
-      - DYNAMIC
+      - origin, accept-encoding
       Access-Control-Allow-Credentials:
       - 'false'
-      Expect-Ct:
-      - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
+      X-Content-Type-Options:
+      - nosniff
       X-Hubspot-Correlation-Id:
-      - 3ca63b6e-9ef1-4aba-9725-a4bddaba0de7
+      - 1b651844-8f46-4b1e-ba1d-5dfa2bd7f2b5
       X-Hubspot-Ratelimit-Daily:
       - '250000'
       X-Hubspot-Ratelimit-Daily-Remaining:
-      - '248133'
+      - '249978'
       X-Hubspot-Ratelimit-Interval-Milliseconds:
       - '10000'
       X-Hubspot-Ratelimit-Max:
       - '100'
       X-Hubspot-Ratelimit-Remaining:
-      - '78'
+      - '96'
       X-Hubspot-Ratelimit-Secondly:
       - '10'
       X-Hubspot-Ratelimit-Secondly-Remaining:
-      - '7'
-      X-Trace:
-      - 2B54B13B6C027B67F49ED5DA2D7C6B77E6460B6FCB000000000000000000
+      - '9'
+      Set-Cookie:
+      - __cf_bm=ezrRUc_pM2WTRKbhS26yGx48FX7TEw4tdZzUpho.zVg-1741174710-1.0.1.1-kv45Teu_daIpCJfR_biEmI.e1vxz1LSH39l78ovO9tho5g0Tfm.afwFtAWgHFw.yvfNHGh3xLx3H3lofflgSGSfkoeKm0GZsPqz29KkcDnk;
+        path=/; expires=Wed, 05-Mar-25 12:08:30 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
       Report-To:
-      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=Hv6kPB8Lki9z2L1rChZekc4HXsqIrdnMLCao0sZYVWgHowRBcgg1x1BxobBrU1DI6qCKPKgCz4xXJaHfRPL49CObTW7GAoXXyqhWgPxb4FiJKqyLWqinu02f7XVoWVukpDk2d5GDmub9seY9"}],"group":"cf-nel","max_age":604800}'
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=itZW1Bc541MbNYiqmfGk%2B0ArCOAUl4tA6tyOjsnmIaRIBGrsYI9e92V4wVxXraOyfJMh8qq3rJyQa2006vLUjDX0ZVEM7D8b7LMqeWofiHNsw6zRR9%2BHf2%2B2ObcU%2FEsXOi7tICc%2FlN1xzp1L"}],"group":"cf-nel","max_age":604800}'
       Nel:
       - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
       Server:
       - cloudflare
-      Alt-Svc:
-      - h3=":443"; ma=86400, h3-29=":443"; ma=86400
     body:
       encoding: ASCII-8BIT
-      string: '[{"portalId":<PORTAL_ID>,"ownerId":156644387,"type":"PERSON","firstName":"Manon","lastName":"Prevot","email":"manon@captaincontrat.com","createdAt":1646901307550,"updatedAt":1651493551619,"remoteList":[{"id":115353728,"portalId":<PORTAL_ID>,"ownerId":156644387,"remoteId":"3905955","remoteType":"HUBSPOT","active":true}],"hasContactsAccess":false,"activeSalesforceId":null,"userIdIncludingInactive":3905955,"activeUserId":3905955,"isActive":true}]'
-  recorded_at: Mon, 08 Aug 2022 14:52:29 GMT
+      string: '{"results":[{"id":"31872455","email":"y[redacted]k@captaincontrat.com","type":"PERSON","firstName":"Yannick","lastName":"F[redacted]","userId":3326038,"userIdIncludingInactive":3326038,"createdAt":"2018-04-09T13:18:57.349Z","updatedAt":"2021-09-23T13:58:43.251Z","archived":false}]}'
+  recorded_at: Wed, 05 Mar 2025 11:38:30 GMT
 - request:
     method: get
-    uri: https://api.hubapi.com/owners/v2/owners?email=yannick@captaincontrat.com&includeInactive=false
+    uri: https://api.hubapi.com/crm/v3/owners?archived=false&email=g%5Bredacted%5Dc@captaincontrat.com&limit=100
     body:
       encoding: US-ASCII
       string: ''
@@ -233,53 +231,53 @@ http_interactions:
       message: OK
     headers:
       Date:
-      - Mon, 08 Aug 2022 14:52:29 GMT
+      - Wed, 05 Mar 2025 11:38:30 GMT
       Content-Type:
       - application/json;charset=utf-8
       Content-Length:
-      - '286'
+      - '283'
       Connection:
       - keep-alive
       Cf-Ray:
-      - 7379137af8483fef-CDG
+      - 91b953d31807d0bc-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Vary:
-      - Accept-Encoding
-      Cf-Cache-Status:
-      - DYNAMIC
+      - origin, Accept-Encoding
       Access-Control-Allow-Credentials:
       - 'false'
-      Expect-Ct:
-      - max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
+      X-Content-Type-Options:
+      - nosniff
       X-Hubspot-Correlation-Id:
-      - f84ad5b5-f867-406d-8d30-948652b9313e
+      - 03c6673b-d769-4a16-aba9-27de7878ba3e
       X-Hubspot-Ratelimit-Daily:
       - '250000'
       X-Hubspot-Ratelimit-Daily-Remaining:
-      - '248132'
+      - '249977'
       X-Hubspot-Ratelimit-Interval-Milliseconds:
       - '10000'
       X-Hubspot-Ratelimit-Max:
       - '100'
       X-Hubspot-Ratelimit-Remaining:
-      - '77'
+      - '95'
       X-Hubspot-Ratelimit-Secondly:
       - '10'
       X-Hubspot-Ratelimit-Secondly-Remaining:
-      - '7'
-      X-Trace:
-      - 2BDD319FF763CCB117797B82C3E07128A10EA52A7E000000000000000000
+      - '9'
+      Set-Cookie:
+      - __cf_bm=pBm4Zf8DiqzAMX7GOtcbgsKU0Zr8t03axfdL2yeZrfg-1741174710-1.0.1.1-1Pg0HOFx69VugBDoaiTQ7H9bIKSb7ZG.BwAjN_gqDOPkH5rRnuJrv9Dtv8EHkz95q_SYLyC58VCFM9t9urYFBIlEE36SZy6o5TdKknMJKaI;
+        path=/; expires=Wed, 05-Mar-25 12:08:30 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
       Report-To:
-      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=gM6WFtFO1M7Sk4GLWi%2BaX%2BC9h6sYL8SDj1pIFLHAc3gesXSo%2Bxu%2ByCfDjsiUqQtlC6QsPpeCvUQ%2F9F36zjUKQFdNBzWAcJX9KPNV%2BK6HjONE5dvEQbwSdyfEZXVozTRIyYAjQKbKXTomzdnh"}],"group":"cf-nel","max_age":604800}'
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=5U13CkqtBuW%2B%2F0mueQwoAo727%2F0TMey%2BS5mssCj9LVM06Nn%2F6x7AfndSV25QNDJT07yI4ja0X%2BzAo72x3p5GXXfk0MgksCMz5dZ2RuOdAnPiUgtbmgRLRv853PkSt16w4Ag1nGXdrwcjnhU1"}],"group":"cf-nel","max_age":604800}'
       Nel:
       - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
       Server:
       - cloudflare
-      Alt-Svc:
-      - h3=":443"; ma=86400, h3-29=":443"; ma=86400
     body:
       encoding: ASCII-8BIT
-      string: '[{"portalId":<PORTAL_ID>,"ownerId":88354160,"type":"PERSON","firstName":"Yannick","lastName":"Fonjallaz","email":"yannick@captaincontrat.com","createdAt":1625489284669,"updatedAt":1632405523288,"remoteList":[{"id":55965105,"portalId":<PORTAL_ID>,"ownerId":88354160,"remoteId":"3326038","remoteType":"HUBSPOT","active":true}],"hasContactsAccess":false,"activeSalesforceId":null,"userIdIncludingInactive":3326038,"activeUserId":3326038,"isActive":true}]'
-  recorded_at: Mon, 08 Aug 2022 14:52:29 GMT
-recorded_with: VCR 6.0.0
+      string: '{"results":[{"id":"414566270","email":"g[redacted]c@captaincontrat.com","type":"PERSON","firstName":"Guillaume","lastName":"C[redacted]","userId":51647443,"userIdIncludingInactive":51647443,"createdAt":"2023-05-22T13:08:58.190Z","updatedAt":"2023-06-20T13:05:15.163Z","archived":false}]}'
+  recorded_at: Wed, 05 Mar 2025 11:38:30 GMT
+recorded_with: VCR 6.3.1
diff --git a/spec/fixtures/vcr_cassettes/owner_find_by_id.yml b/spec/fixtures/vcr_cassettes/owner_find_by_id.yml
new file mode 100644
index 00000000..46fdc2a4
--- /dev/null
+++ b/spec/fixtures/vcr_cassettes/owner_find_by_id.yml
@@ -0,0 +1,143 @@
+---
+http_interactions:
+- request:
+    method: get
+    uri: https://api.hubapi.com/crm/v3/owners?archived=false&email=31871817
+    body:
+      encoding: US-ASCII
+      string: ''
+    headers:
+      Authorization:
+      - Bearer <ACCESS_TOKEN>
+      Accept-Encoding:
+      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+      Accept:
+      - "*/*"
+      User-Agent:
+      - Ruby
+  response:
+    status:
+      code: 200
+      message: OK
+    headers:
+      Date:
+      - Wed, 05 Mar 2025 11:39:28 GMT
+      Content-Type:
+      - application/json;charset=utf-8
+      Content-Length:
+      - '14'
+      Connection:
+      - keep-alive
+      Cf-Ray:
+      - 91b9553e4f2d8b21-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
+      Strict-Transport-Security:
+      - max-age=31536000; includeSubDomains; preload
+      Vary:
+      - origin, Accept-Encoding
+      Access-Control-Allow-Credentials:
+      - 'false'
+      X-Content-Type-Options:
+      - nosniff
+      X-Hubspot-Correlation-Id:
+      - 4fe57f32-bff9-470f-a63b-9e126cc7b479
+      X-Hubspot-Ratelimit-Daily:
+      - '250000'
+      X-Hubspot-Ratelimit-Daily-Remaining:
+      - '249976'
+      X-Hubspot-Ratelimit-Interval-Milliseconds:
+      - '10000'
+      X-Hubspot-Ratelimit-Max:
+      - '100'
+      X-Hubspot-Ratelimit-Remaining:
+      - '99'
+      X-Hubspot-Ratelimit-Secondly:
+      - '10'
+      X-Hubspot-Ratelimit-Secondly-Remaining:
+      - '9'
+      Set-Cookie:
+      - __cf_bm=IKarCiBnq3bobAGws9D0OS1w5ACB_KVyadovajFRQyw-1741174768-1.0.1.1-FhVLUarcHM2XVaDzeskoRPvGBrbZL2CnuFd_PLi6QTVyi0WhX1.8nHhApm93m8LVAnyrClDR9vvHwl90xwRtkenH.ZGTSg.5Z2_9GraHx.s;
+        path=/; expires=Wed, 05-Mar-25 12:09:28 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
+      Report-To:
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=ZYwy4fhmR%2BIpeUX1%2FzdpBNNMZgqc0nEVoMX7ItMPwj43iJR1xCRJzgf%2FqSY9j%2BW7oekPdfBnJ9cM6BYBnbeRgrotM8fmybo%2FukzQPGWE2GzC6kUs%2BLAfJO4SKsxsowCU%2BGOHHOmNpMaKQSKZ"}],"group":"cf-nel","max_age":604800}'
+      Nel:
+      - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
+      Server:
+      - cloudflare
+    body:
+      encoding: UTF-8
+      string: '{"results":[]}'
+  recorded_at: Wed, 05 Mar 2025 11:39:28 GMT
+- request:
+    method: get
+    uri: https://api.hubapi.com/crm/v3/owners/31871817
+    body:
+      encoding: US-ASCII
+      string: ''
+    headers:
+      Authorization:
+      - Bearer <ACCESS_TOKEN>
+      Accept-Encoding:
+      - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+      Accept:
+      - "*/*"
+      User-Agent:
+      - Ruby
+  response:
+    status:
+      code: 200
+      message: OK
+    headers:
+      Date:
+      - Wed, 05 Mar 2025 11:39:43 GMT
+      Content-Type:
+      - application/json;charset=utf-8
+      Content-Length:
+      - '260'
+      Connection:
+      - keep-alive
+      Cf-Ray:
+      - 91b9559b5d9bab52-CDG
+      Cf-Cache-Status:
+      - DYNAMIC
+      Strict-Transport-Security:
+      - max-age=31536000; includeSubDomains; preload
+      Vary:
+      - origin, accept-encoding
+      Access-Control-Allow-Credentials:
+      - 'false'
+      X-Content-Type-Options:
+      - nosniff
+      X-Hubspot-Correlation-Id:
+      - ad3910a5-45fa-4e4a-8615-3d2ce077262b
+      X-Hubspot-Ratelimit-Daily:
+      - '250000'
+      X-Hubspot-Ratelimit-Daily-Remaining:
+      - '249975'
+      X-Hubspot-Ratelimit-Interval-Milliseconds:
+      - '10000'
+      X-Hubspot-Ratelimit-Max:
+      - '100'
+      X-Hubspot-Ratelimit-Remaining:
+      - '99'
+      X-Hubspot-Ratelimit-Secondly:
+      - '10'
+      X-Hubspot-Ratelimit-Secondly-Remaining:
+      - '9'
+      Set-Cookie:
+      - __cf_bm=oV5aKRJRy5KDlmuDUW5QMMCdpP.6G85hp.RHY_nrBhg-1741174783-1.0.1.1-1EAw3xlz8h6pio2tkqd1Jl1fWl_oo69mwwmrARCMyUuMzmhp7pTxYGOh4MwVMqYXI1LKhxY8NtVNFnYu2XJ7P_qlJT5OjdA73dS3Ar6aEe4;
+        path=/; expires=Wed, 05-Mar-25 12:09:43 GMT; domain=.hubapi.com; HttpOnly;
+        Secure; SameSite=None
+      Report-To:
+      - '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=dU1TKkyFAG4WZ6rVzSB%2BZjOUmaJPOPpmAbY%2F%2BM%2BfASt57LBPbD0VVSXHHdWHz%2FDvSGJUEReZU6SYfSBwJp%2FoJpJ%2B9ntvC1VOBQ3TxMoDoBUv4aXg%2FoJkz4XyH272dSaZx8oHocqRb6szwMLP"}],"group":"cf-nel","max_age":604800}'
+      Nel:
+      - '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
+      Server:
+      - cloudflare
+    body:
+      encoding: ASCII-8BIT
+      string: '{"id":"31871817","email":"p[redacted]e@captaincontrat.com","type":"PERSON","firstName":"Philippe","lastName":"W[redacted]","userId":2506672,"userIdIncludingInactive":2506672,"createdAt":"2018-04-09T13:16:56.625Z","updatedAt":"2018-04-09T13:16:56.625Z","archived":false}'
+  recorded_at: Wed, 05 Mar 2025 11:39:43 GMT
+recorded_with: VCR 6.3.1
diff --git a/spec/lib/hubspot/owner_spec.rb b/spec/lib/hubspot/owner_spec.rb
index 39f594c6..4edd2fa3 100644
--- a/spec/lib/hubspot/owner_spec.rb
+++ b/spec/lib/hubspot/owner_spec.rb
@@ -2,7 +2,7 @@
   let(:example_owners) do
     VCR.use_cassette('owner_example') do
       headers = { Authorization: "Bearer #{ENV.fetch('HUBSPOT_ACCESS_TOKEN')}" }
-      HTTParty.get('https://api.hubapi.com/owners/v2/owners', headers: headers).parsed_response
+      HTTParty.get('https://api.hubapi.com/crm/v3/owners', headers: headers).parsed_response['results']
     end
   end
 
@@ -13,7 +13,22 @@
       owners = Hubspot::Owner.all
 
       expect(owners.blank?).to be false
-      compare_owners(owners, example_owners)
+      expect(owners[:results].blank?).to be false
+      compare_owners(owners[:results], example_owners)
+    end
+  end
+
+  describe '.find' do
+    cassette 'owner_find_by_id'
+
+    let(:sample) { example_owners.first }
+    let(:id) { sample['id'] }
+
+    it 'should find a user via their id' do
+      owner = Hubspot::Owner.find(id)
+      sample.map do |key, val|
+        expect(owner[key]).to eq(val)
+      end
     end
   end
 


Reviews:
user: login: fonji
body: Looks really cool! Thank you very much :bow: 
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-05T08:56:32Z
user: login: Paul-Yves
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-06T13:04:28Z
user: login: kpgdev
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-06T16:19:45Z
user: login: kpgdev
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-06T16:22:43Z
user: login: Paul-Yves
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-06T16:27:29Z
user: login: kpgdev
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-06T16:38:39Z
user: login: Paul-Yves
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-06T16:41:55Z
user: login: fonji
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-06T16:42:02Z
user: login: fonji
body: Thank you very much @kpgdev :bow: 
state: APPROVED
author_association: NONE
submitted_at: 2025-03-07T08:58:57Z
user: login: Paul-Yves
state: APPROVED
author_association: NONE
submitted_at: 2025-03-07T09:00:14Z

Review comments:
diff_hunk: @@ -28,29 +25,48 @@ def [](property)
     end
 
     class << self
-      def all(include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { includeInactive: include_inactive }
+      def all(include_archived: false, limit: 100, after: nil, id_property: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          archived: include_archived,
+          limit: limit,
+          after: after,
+          idProperty: id_property
+        }.compact
+
         response = Hubspot::Connection.get_json(path, params)
-        response.map { |r| new(r) }
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find(id, include_inactive=false)
-        path     = GET_OWNER_PATH
-        response = Hubspot::Connection.get_json(path, owner_id: id,
-          include_inactive: include_inactive)
+      def find(id, id_property: nil)
+        path = GET_OWNER_PATH
+        params = { owner_id: id }
+        params[:idProperty] = id_property if id_property
+        response = Hubspot::Connection.get_json(path, params)
         new(response)
       end
 
-      def find_by_email(email, include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { email: email, includeInactive: include_inactive }
+      def find_by_email(email, include_archived: false, id_property: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          email: email,
+          archived: include_archived,
+          idProperty: id_property
path: lib/hubspot/owner.rb
user: login: Paul-Yves
body: Will it work if nil or should we have default value as `id` ? By the way, if it's by email, shouldn't the idProperty be email (and email key be owner_id) ? I can't find the API reference for an email parameter
created_at: 2025-03-06T13:04:28Z
author_association: NONE
diff_hunk: @@ -28,29 +25,48 @@ def [](property)
     end
 
     class << self
-      def all(include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { includeInactive: include_inactive }
+      def all(include_archived: false, limit: 100, after: nil, id_property: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          archived: include_archived,
+          limit: limit,
+          after: after,
+          idProperty: id_property
+        }.compact
+
         response = Hubspot::Connection.get_json(path, params)
-        response.map { |r| new(r) }
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find(id, include_inactive=false)
-        path     = GET_OWNER_PATH
-        response = Hubspot::Connection.get_json(path, owner_id: id,
-          include_inactive: include_inactive)
+      def find(id, id_property: nil)
+        path = GET_OWNER_PATH
+        params = { owner_id: id }
+        params[:idProperty] = id_property if id_property
+        response = Hubspot::Connection.get_json(path, params)
         new(response)
       end
 
-      def find_by_email(email, include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { email: email, includeInactive: include_inactive }
+      def find_by_email(email, include_archived: false, id_property: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          email: email,
+          archived: include_archived,
+          idProperty: id_property
path: lib/hubspot/owner.rb
user: login: kpgdev
body: apologies AI messed this up. I've corrected the method signatures

 idProperty is not available on owners only owner. 
 
 I've also adjusted to add paging onto the owners search by email. 
 
 the collection that is returned is nested in `results`. perhaps this needs to removed so the collection is flat 
 
created_at: 2025-03-06T16:19:45Z
author_association: NONE
diff_hunk: @@ -52,20 +51,27 @@ def find(id, id_property: nil)
         new(response)
       end
 
-      def find_by_email(email, include_archived: false, id_property: nil)
+      def find_by_email(email, include_archived: false, limit: 100, after: nil)
         path = GET_OWNERS_PATH
         params = {
           email: email,
           archived: include_archived,
-          idProperty: id_property
+          limit: limit,
+          after: after
         }.compact
         response = Hubspot::Connection.get_json(path, params)
-        response['results'].empty? ? nil : new(response['results'].first)
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
path: lib/hubspot/owner.rb
user: login: kpgdev
body: Could return multiple HS owners of the same email?
created_at: 2025-03-06T16:22:42Z
author_association: NONE
diff_hunk: @@ -28,29 +25,54 @@ def [](property)
     end
 
     class << self
-      def all(include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { includeInactive: include_inactive }
+      def all(include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
+
         response = Hubspot::Connection.get_json(path, params)
-        response.map { |r| new(r) }
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find(id, include_inactive=false)
-        path     = GET_OWNER_PATH
-        response = Hubspot::Connection.get_json(path, owner_id: id,
-          include_inactive: include_inactive)
+      def find(id, id_property: nil)
+        path = GET_OWNER_PATH
+        params = { owner_id: id }
+        params[:idProperty] = id_property if id_property
+        response = Hubspot::Connection.get_json(path, params)
         new(response)
       end
 
-      def find_by_email(email, include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { email: email, includeInactive: include_inactive }
+      def find_by_email(email, include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          email: email,
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
         response = Hubspot::Connection.get_json(path, params)
-        response.blank? ? nil : new(response.first)
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find_by_emails(emails, include_inactive=false)
-        emails.map { |email| find_by_email(email, include_inactive) }.reject(&:blank?)
+      def find_by_emails(emails, include_archived: false)
+        emails.map { |email| 
+          find_by_email(email, include_archived: include_archived) 
+        }.reject(&:blank?)
path: lib/hubspot/owner.rb
user: login: Paul-Yves
body: I doubt this `reject(&:blank?)` will work, my guess is that worse case, you will have a list of hashes with empty results.
If we want to keep the current signature of the methods, you would rather need to flatten all results in the same array. However we now loose the pagination information. This seems acceptable to me since a search by email won't likely result in more than 100 elements (but maybe should be documented)
created_at: 2025-03-06T16:27:29Z
author_association: NONE
diff_hunk: @@ -28,29 +25,54 @@ def [](property)
     end
 
     class << self
-      def all(include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { includeInactive: include_inactive }
+      def all(include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
+
         response = Hubspot::Connection.get_json(path, params)
-        response.map { |r| new(r) }
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find(id, include_inactive=false)
-        path     = GET_OWNER_PATH
-        response = Hubspot::Connection.get_json(path, owner_id: id,
-          include_inactive: include_inactive)
+      def find(id, id_property: nil)
+        path = GET_OWNER_PATH
+        params = { owner_id: id }
+        params[:idProperty] = id_property if id_property
+        response = Hubspot::Connection.get_json(path, params)
         new(response)
       end
 
-      def find_by_email(email, include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { email: email, includeInactive: include_inactive }
+      def find_by_email(email, include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          email: email,
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
         response = Hubspot::Connection.get_json(path, params)
-        response.blank? ? nil : new(response.first)
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find_by_emails(emails, include_inactive=false)
-        emails.map { |email| find_by_email(email, include_inactive) }.reject(&:blank?)
+      def find_by_emails(emails, include_archived: false)
+        emails.map { |email| 
+          find_by_email(email, include_archived: include_archived) 
+        }.reject(&:blank?)
path: lib/hubspot/owner.rb
user: login: kpgdev
body: makes sense - should the all behave in the same way for constancy?  thus:

all and find_by_emails - collection
find and find_by_email - single 
created_at: 2025-03-06T16:38:38Z
author_association: NONE
diff_hunk: @@ -28,29 +25,54 @@ def [](property)
     end
 
     class << self
-      def all(include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { includeInactive: include_inactive }
+      def all(include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
+
         response = Hubspot::Connection.get_json(path, params)
-        response.map { |r| new(r) }
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find(id, include_inactive=false)
-        path     = GET_OWNER_PATH
-        response = Hubspot::Connection.get_json(path, owner_id: id,
-          include_inactive: include_inactive)
+      def find(id, id_property: nil)
+        path = GET_OWNER_PATH
+        params = { owner_id: id }
+        params[:idProperty] = id_property if id_property
+        response = Hubspot::Connection.get_json(path, params)
         new(response)
       end
 
-      def find_by_email(email, include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { email: email, includeInactive: include_inactive }
+      def find_by_email(email, include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          email: email,
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
         response = Hubspot::Connection.get_json(path, params)
-        response.blank? ? nil : new(response.first)
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find_by_emails(emails, include_inactive=false)
-        emails.map { |email| find_by_email(email, include_inactive) }.reject(&:blank?)
+      def find_by_emails(emails, include_archived: false)
+        emails.map { |email| 
+          find_by_email(email, include_archived: include_archived) 
+        }.reject(&:blank?)
path: lib/hubspot/owner.rb
user: login: Paul-Yves
body: all and find as for now are ok to me (especially all should return the pagination detail) but yes maybe find_by_email and find_by_emails should be consistent with previous behaviour
created_at: 2025-03-06T16:41:54Z
author_association: NONE
diff_hunk: @@ -28,29 +25,54 @@ def [](property)
     end
 
     class << self
-      def all(include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { includeInactive: include_inactive }
+      def all(include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
+
         response = Hubspot::Connection.get_json(path, params)
-        response.map { |r| new(r) }
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find(id, include_inactive=false)
-        path     = GET_OWNER_PATH
-        response = Hubspot::Connection.get_json(path, owner_id: id,
-          include_inactive: include_inactive)
+      def find(id, id_property: nil)
+        path = GET_OWNER_PATH
+        params = { owner_id: id }
+        params[:idProperty] = id_property if id_property
+        response = Hubspot::Connection.get_json(path, params)
         new(response)
       end
 
-      def find_by_email(email, include_inactive=false)
-        path     = GET_OWNERS_PATH
-        params   = { email: email, includeInactive: include_inactive }
+      def find_by_email(email, include_archived: false, limit: 100, after: nil)
+        path = GET_OWNERS_PATH
+        params = {
+          email: email,
+          archived: include_archived,
+          limit: limit,
+          after: after
+        }.compact
         response = Hubspot::Connection.get_json(path, params)
-        response.blank? ? nil : new(response.first)
+        {
+          results: response['results'].map { |r| new(r) },
+          pagination: {
+            next: response['paging']&.dig('next', 'after'),
+            total: response['total']
+          }
+        }
       end
 
-      def find_by_emails(emails, include_inactive=false)
-        emails.map { |email| find_by_email(email, include_inactive) }.reject(&:blank?)
+      def find_by_emails(emails, include_archived: false)
+        emails.map { |email| 
+          find_by_email(email, include_archived: include_archived) 
+        }.reject(&:blank?)
path: lib/hubspot/owner.rb
user: login: fonji
body: It would be very nice if we could make a single request with multiple emails
so find_by_emails would make the request
find_by_email would use find_by_emails and return the first result (or nil)
created_at: 2025-03-06T16:42:02Z
author_association: NONE

PR comments:
user: login: fonji
created_at: 2025-03-06T09:28:24Z
body: Ungh why does actions run on your side
author_association: NONE
user: login: fonji
created_at: 2025-03-06T09:33:55Z
body: Can you add `HUBSPOT_ACCESS_TOKEN`, `HUBSPOT_HAPI_KEY` and `HUBSPOT_PORTAL_ID` in https://github.com/kpdev/hubspot-api-ruby/settings/secrets/actions?
I think you can put fake values.
Then we'll re-run actions and see if it is green
author_association: NONE
user: login: kpgdev
created_at: 2025-03-06T12:35:04Z
body: Added secrets
author_association: NONE
user: login: fonji
created_at: 2025-03-07T09:00:17Z
body: For the record: specs are :white_check_mark: https://github.com/kpgdev/hubspot-api-ruby/actions/runs/13717193701
author_association: NONE
user: login: fonji
created_at: 2025-03-07T09:02:42Z
body: Published! :tada: 
author_association: NONE