diff --git a/CHANGELOG.md b/CHANGELOG.md index 3054a8a0..45503e65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # CHANGELOG +## v7.4.0 (2026-02-02) + +- Adds the following functions usable by child and referral customer users: + - `api_key.create` + - `api_key.delete` + - `api_key.enable` + - `api_key.disable` + ## v7.3.0 (2025-11-24) - Adds the following functions: diff --git a/VERSION b/VERSION index 15020207..ba7f754d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.3.0 +7.4.0 diff --git a/lib/easypost/services/api_key.rb b/lib/easypost/services/api_key.rb index 6bb1e98e..6223a506 100644 --- a/lib/easypost/services/api_key.rb +++ b/lib/easypost/services/api_key.rb @@ -1,11 +1,13 @@ # frozen_string_literal: true class EasyPost::Services::ApiKey < EasyPost::Services::Service + MODEL_CLASS = EasyPost::Models::ApiKey # :nodoc: + # Retrieve a list of all ApiKey objects. def all response = @client.make_request(:get, 'api_keys') - EasyPost::InternalUtilities::Json.convert_json_to_object(response, EasyPost::Models::ApiKey) + EasyPost::InternalUtilities::Json.convert_json_to_object(response, MODEL_CLASS) end # Retrieve a list of ApiKey objects (works for the authenticated user or a child user). @@ -26,4 +28,33 @@ def retrieve_api_keys_for_user(id) raise EasyPost::Errors::FilteringError.new(EasyPost::Constants::NO_USER_FOUND) end + + # Create an API key for a child or referral customer user + def create(mode) + response = @client.make_request(:post, 'api_keys', { mode: mode }) + + EasyPost::InternalUtilities::Json.convert_json_to_object(response, MODEL_CLASS) + end + + # Delete an API key for a child or referral customer user + def delete(id) + @client.make_request(:delete, "api_keys/#{id}") + + # Return true if succeeds, an error will be thrown if it fails + true + end + + # Enable an API key for a child or referral customer user + def enable(id) + response = @client.make_request(:post, "api_keys/#{id}/enable") + + EasyPost::InternalUtilities::Json.convert_json_to_object(response, MODEL_CLASS) + end + + # Disable an API key for a child or referral customer user + def disable(id) + response = @client.make_request(:post, "api_keys/#{id}/disable") + + EasyPost::InternalUtilities::Json.convert_json_to_object(response, MODEL_CLASS) + end end diff --git a/spec/api_key_spec.rb b/spec/api_key_spec.rb index 04c4f98b..9f1b96d7 100644 --- a/spec/api_key_spec.rb +++ b/spec/api_key_spec.rb @@ -37,4 +37,27 @@ client.user.delete(user.id) # delete the user so we don't clutter the test environment end end + + describe 'API key lifecycle' do + let(:referral_client) { EasyPost::Client.new(api_key: ENV['REFERRAL_CUSTOMER_PROD_API_KEY'] || '123') } + + it 'creates, enables, disables, and deletes an API key for a referral customer' do + # Create + api_key = referral_client.api_key.create('production') + expect(api_key).to be_an_instance_of(EasyPost::Models::ApiKey) + expect(api_key.id).to match('ak_') + expect(api_key.mode).to eq('production') + + # Disable + disabled_key = referral_client.api_key.disable(api_key.id) + expect(disabled_key.active).to be false + + # Enable + enabled_key = referral_client.api_key.enable(api_key.id) + expect(enabled_key.active).to be true + + # Delete + referral_client.api_key.delete(api_key.id) + end + end end diff --git a/spec/cassettes/api_key/EasyPost_Services_ApiKey_API_key_lifecycle_creates_enables_disables_and_deletes_an_API_key_for_a_referral_customer.yml b/spec/cassettes/api_key/EasyPost_Services_ApiKey_API_key_lifecycle_creates_enables_disables_and_deletes_an_API_key_for_a_referral_customer.yml new file mode 100644 index 00000000..4212de28 --- /dev/null +++ b/spec/cassettes/api_key/EasyPost_Services_ApiKey_API_key_lifecycle_creates_enables_disables_and_deletes_an_API_key_for_a_referral_customer.yml @@ -0,0 +1,253 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.easypost.com/v2/api_keys + body: + encoding: UTF-8 + string: '{"mode":"production"}' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: "" + Host: + - api.easypost.com + Content-Type: + - application/json + Authorization: "" + response: + status: + code: 201 + message: Created + headers: + X-Frame-Options: + - SAMEORIGIN + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Permitted-Cross-Domain-Policies: + - none + Referrer-Policy: + - strict-origin-when-cross-origin + X-Ep-Request-Uuid: + - 2e56ccf06981140ae2baa53c02cc4fce + Cache-Control: + - private, no-cache, no-store + Pragma: + - no-cache + Expires: + - '0' + Content-Type: + - application/json; charset=utf-8 + X-Runtime: + - '0.089773' + Transfer-Encoding: + - chunked + X-Node: + - bigweb34nuq + X-Version-Label: + - easypost-202602022023-e2aafa4ad5-master + X-Backend: + - easypost + X-Proxied: + - extlb2nuq cbbd141214 + - intlb4nuq d9379ca146 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + body: + encoding: UTF-8 + string: '{"object":"ApiKey","key":"","mode":"production","created_at":"2026-02-02T21:15:54Z","active":true,"id":"ak_8de38f77277f420baffd2e6834ad65a2"}' + recorded_at: Mon, 02 Feb 2026 21:15:54 GMT +- request: + method: post + uri: https://api.easypost.com/v2/api_keys/ak_8de38f77277f420baffd2e6834ad65a2/disable + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: "" + Host: + - api.easypost.com + Content-Type: + - application/json + Authorization: "" + response: + status: + code: 200 + message: OK + headers: + X-Frame-Options: + - SAMEORIGIN + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Permitted-Cross-Domain-Policies: + - none + Referrer-Policy: + - strict-origin-when-cross-origin + X-Ep-Request-Uuid: + - 2e56ccf36981140ae2baa53e02cc5014 + Cache-Control: + - private, no-cache, no-store + Pragma: + - no-cache + Expires: + - '0' + Content-Type: + - application/json; charset=utf-8 + X-Runtime: + - '0.113790' + Transfer-Encoding: + - chunked + X-Node: + - bigweb43nuq + X-Version-Label: + - easypost-202602022023-e2aafa4ad5-master + X-Backend: + - easypost + X-Canary: + - direct + X-Proxied: + - extlb2nuq cbbd141214 + - intlb5nuq d9379ca146 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + body: + encoding: UTF-8 + string: '{"object":"ApiKey","key":"","mode":"production","created_at":"2026-02-02T21:15:54Z","active":false,"id":"ak_8de38f77277f420baffd2e6834ad65a2"}' + recorded_at: Mon, 02 Feb 2026 21:15:54 GMT +- request: + method: post + uri: https://api.easypost.com/v2/api_keys/ak_8de38f77277f420baffd2e6834ad65a2/enable + body: + encoding: UTF-8 + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: "" + Host: + - api.easypost.com + Content-Type: + - application/json + Authorization: "" + response: + status: + code: 200 + message: OK + headers: + X-Frame-Options: + - SAMEORIGIN + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Permitted-Cross-Domain-Policies: + - none + Referrer-Policy: + - strict-origin-when-cross-origin + X-Ep-Request-Uuid: + - 2e56ccf06981140ae2baa54102cc5083 + Cache-Control: + - private, no-cache, no-store + Pragma: + - no-cache + Expires: + - '0' + Content-Type: + - application/json; charset=utf-8 + X-Runtime: + - '0.243929' + Transfer-Encoding: + - chunked + X-Node: + - bigweb54nuq + X-Version-Label: + - easypost-202602022023-e2aafa4ad5-master + X-Backend: + - easypost + X-Proxied: + - extlb2nuq cbbd141214 + - intlb6nuq d9379ca146 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + body: + encoding: UTF-8 + string: '{"object":"ApiKey","key":"","mode":"production","created_at":"2026-02-02T21:15:54Z","active":true,"id":"ak_8de38f77277f420baffd2e6834ad65a2"}' + recorded_at: Mon, 02 Feb 2026 21:15:55 GMT +- request: + method: delete + uri: https://api.easypost.com/v2/api_keys/ak_8de38f77277f420baffd2e6834ad65a2 + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: "" + Host: + - api.easypost.com + Content-Type: + - application/json + Authorization: "" + response: + status: + code: 204 + message: No Content + headers: + X-Frame-Options: + - SAMEORIGIN + X-Xss-Protection: + - 1; mode=block + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Permitted-Cross-Domain-Policies: + - none + Referrer-Policy: + - strict-origin-when-cross-origin + X-Ep-Request-Uuid: + - cfd5bd426981140be2baa55e02807d59 + Cache-Control: + - private, no-cache, no-store + Pragma: + - no-cache + Expires: + - '0' + X-Runtime: + - '0.134902' + X-Node: + - bigweb36nuq + X-Version-Label: + - easypost-202602022023-e2aafa4ad5-master + X-Backend: + - easypost + X-Proxied: + - extlb1nuq cbbd141214 + - intlb6nuq d9379ca146 + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + body: + encoding: UTF-8 + string: '' + recorded_at: Mon, 02 Feb 2026 21:15:55 GMT +recorded_with: VCR 6.4.0