From db18797c7a1b77db74cd0b0de87b0b9901aa4032 Mon Sep 17 00:00:00 2001 From: Mark Dobbins Date: Tue, 4 Aug 2026 14:12:15 +0100 Subject: [PATCH] Migrate OAuth token endpoints to the 2026-03 API (OME-796) HubSpot sunsets the legacy /oauth/v1/ token endpoints on 2027-02-16. Move the three OAuth codegen operations to the 2026-03 replacements: - TokensApi#create: POST /oauth/v1/token -> POST /oauth/2026-03/token (already form-encoded; response is identical, so no model change). - AccessTokensApi#get and RefreshTokensApi#get: GET /oauth/v1/{access,refresh}-tokens/{token} -> POST /oauth/2026-03/token/introspect, with token, token_type_hint, client_id and client_secret sent as form-body params (never in the URL). Introspection returns a raw hash rather than a strict model, since the 2026-03 introspect fields differ from v1. - RefreshTokensApi#archive: DELETE /oauth/v1/refresh-tokens/{token} -> POST /oauth/2026-03/token/revoke, token in the form body. Method names/signatures are unchanged so callers are unaffected. No /oauth/v1/ path remains in the gem. --- .../codegen/oauth/api/access_tokens_api.rb | 19 ++++++++--- .../codegen/oauth/api/refresh_tokens_api.rb | 32 ++++++++++++++----- lib/hubspot/codegen/oauth/api/tokens_api.rb | 2 +- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/hubspot/codegen/oauth/api/access_tokens_api.rb b/lib/hubspot/codegen/oauth/api/access_tokens_api.rb index a1291e435..da90e7f0c 100644 --- a/lib/hubspot/codegen/oauth/api/access_tokens_api.rb +++ b/lib/hubspot/codegen/oauth/api/access_tokens_api.rb @@ -39,8 +39,9 @@ def get_with_http_info(token, opts = {}) if @api_client.config.client_side_validation && token.nil? fail ArgumentError, "Missing the required parameter 'token' when calling AccessTokensApi.get" end - # resource path - local_var_path = '/oauth/v1/access-tokens/{token}'.sub('{' + 'token' + '}', CGI.escape(token.to_s)) + # resource path: introspection moved to POST /oauth/2026-03/token/introspect; + # the token is sent as a form-body parameter, never in the URL. + local_var_path = '/oauth/2026-03/token/introspect' # query parameters query_params = opts[:query_params] || {} @@ -49,15 +50,23 @@ def get_with_http_info(token, opts = {}) header_params = opts[:header_params] || {} # HTTP header 'Accept' (if needed) header_params['Accept'] = @api_client.select_header_accept(['application/json', '*/*']) + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/x-www-form-urlencoded']) + header_params['Content-Type'] = content_type unless content_type.nil? # form parameters form_params = opts[:form_params] || {} + form_params['token'] = token + form_params['token_type_hint'] = opts[:'token_type_hint'] || 'access_token' + form_params['client_id'] = opts[:'client_id'] if !opts[:'client_id'].nil? + form_params['client_secret'] = opts[:'client_secret'] if !opts[:'client_secret'].nil? # http body (model) post_body = opts[:debug_body] - # return_type - return_type = opts[:debug_return_type] || 'AccessTokenInfoResponse' + # return_type: introspection response is read as a raw hash so the mapping is not + # coupled to a strict model as HubSpot iterates the 2026-03 introspect fields. + return_type = opts[:debug_return_type] || 'Object' # auth_names auth_names = opts[:debug_auth_names] || [] @@ -72,7 +81,7 @@ def get_with_http_info(token, opts = {}) :return_type => return_type ) - data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) if @api_client.config.debugging @api_client.config.logger.debug "API called: AccessTokensApi#get\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" end diff --git a/lib/hubspot/codegen/oauth/api/refresh_tokens_api.rb b/lib/hubspot/codegen/oauth/api/refresh_tokens_api.rb index 3335a8da8..175725eb4 100644 --- a/lib/hubspot/codegen/oauth/api/refresh_tokens_api.rb +++ b/lib/hubspot/codegen/oauth/api/refresh_tokens_api.rb @@ -39,8 +39,9 @@ def archive_with_http_info(token, opts = {}) if @api_client.config.client_side_validation && token.nil? fail ArgumentError, "Missing the required parameter 'token' when calling RefreshTokensApi.archive" end - # resource path - local_var_path = '/oauth/v1/refresh-tokens/{token}'.sub('{' + 'token' + '}', CGI.escape(token.to_s)) + # resource path: revocation moved to POST /oauth/2026-03/token/revoke; + # the token is sent as a form-body parameter, never in the URL. + local_var_path = '/oauth/2026-03/token/revoke' # query parameters query_params = opts[:query_params] || {} @@ -49,9 +50,15 @@ def archive_with_http_info(token, opts = {}) header_params = opts[:header_params] || {} # HTTP header 'Accept' (if needed) header_params['Accept'] = @api_client.select_header_accept(['*/*']) + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/x-www-form-urlencoded']) + header_params['Content-Type'] = content_type unless content_type.nil? # form parameters form_params = opts[:form_params] || {} + form_params['token'] = token + form_params['client_id'] = opts[:'client_id'] if !opts[:'client_id'].nil? + form_params['client_secret'] = opts[:'client_secret'] if !opts[:'client_secret'].nil? # http body (model) post_body = opts[:debug_body] @@ -72,7 +79,7 @@ def archive_with_http_info(token, opts = {}) :return_type => return_type ) - data, status_code, headers = @api_client.call_api(:DELETE, local_var_path, new_options) + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) if @api_client.config.debugging @api_client.config.logger.debug "API called: RefreshTokensApi#archive\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" end @@ -98,8 +105,9 @@ def get_with_http_info(token, opts = {}) if @api_client.config.client_side_validation && token.nil? fail ArgumentError, "Missing the required parameter 'token' when calling RefreshTokensApi.get" end - # resource path - local_var_path = '/oauth/v1/refresh-tokens/{token}'.sub('{' + 'token' + '}', CGI.escape(token.to_s)) + # resource path: introspection moved to POST /oauth/2026-03/token/introspect; + # the token is sent as a form-body parameter, never in the URL. + local_var_path = '/oauth/2026-03/token/introspect' # query parameters query_params = opts[:query_params] || {} @@ -108,15 +116,23 @@ def get_with_http_info(token, opts = {}) header_params = opts[:header_params] || {} # HTTP header 'Accept' (if needed) header_params['Accept'] = @api_client.select_header_accept(['application/json', '*/*']) + # HTTP header 'Content-Type' + content_type = @api_client.select_header_content_type(['application/x-www-form-urlencoded']) + header_params['Content-Type'] = content_type unless content_type.nil? # form parameters form_params = opts[:form_params] || {} + form_params['token'] = token + form_params['token_type_hint'] = opts[:'token_type_hint'] || 'refresh_token' + form_params['client_id'] = opts[:'client_id'] if !opts[:'client_id'].nil? + form_params['client_secret'] = opts[:'client_secret'] if !opts[:'client_secret'].nil? # http body (model) post_body = opts[:debug_body] - # return_type - return_type = opts[:debug_return_type] || 'RefreshTokenInfoResponse' + # return_type: introspection response is read as a raw hash so the mapping is not + # coupled to a strict model as HubSpot iterates the 2026-03 introspect fields. + return_type = opts[:debug_return_type] || 'Object' # auth_names auth_names = opts[:debug_auth_names] || [] @@ -131,7 +147,7 @@ def get_with_http_info(token, opts = {}) :return_type => return_type ) - data, status_code, headers = @api_client.call_api(:GET, local_var_path, new_options) + data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options) if @api_client.config.debugging @api_client.config.logger.debug "API called: RefreshTokensApi#get\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}" end diff --git a/lib/hubspot/codegen/oauth/api/tokens_api.rb b/lib/hubspot/codegen/oauth/api/tokens_api.rb index 4c6cfb093..3390a42a6 100644 --- a/lib/hubspot/codegen/oauth/api/tokens_api.rb +++ b/lib/hubspot/codegen/oauth/api/tokens_api.rb @@ -50,7 +50,7 @@ def create_with_http_info(opts = {}) fail ArgumentError, "invalid value for \"grant_type\", must be one of #{allowable_values}" end # resource path - local_var_path = '/oauth/v1/token' + local_var_path = '/oauth/2026-03/token' # query parameters query_params = opts[:query_params] || {}