From d36a5f167f5c3a12f7d5c03c7deced1179b638e2 Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Thu, 12 Feb 2026 10:32:48 -0700 Subject: [PATCH 1/2] feat: add a generic API request interface This public, generic interface is useful for making arbitrary API calls to the EasyPost API that are not yet supported by the client library's services. When possible, the service for your use case should be used instead as it provides a more convenient and higher-level interface depending on the endpoint. Co-Authored-By: Claude Sonnet 4.5 --- lib/EasyPost/EasyPostClient.php | 21 +++++++ test/EasyPost/EasyPostClientTest.php | 31 ++++++++++ test/cassettes/client/makeApiCall.yml | 84 +++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 test/cassettes/client/makeApiCall.yml diff --git a/lib/EasyPost/EasyPostClient.php b/lib/EasyPost/EasyPostClient.php index e5d14889..2bbc94af 100644 --- a/lib/EasyPost/EasyPostClient.php +++ b/lib/EasyPost/EasyPostClient.php @@ -6,7 +6,9 @@ use EasyPost\Exception\General\EasyPostException; use EasyPost\Hook\RequestHook; use EasyPost\Hook\ResponseHook; +use EasyPost\Http\Requestor; use EasyPost\Service\AddressService; +use EasyPost\Util\InternalUtil; use EasyPost\Service\ApiKeyService; use EasyPost\Service\BaseService; use EasyPost\Service\BatchService; @@ -260,4 +262,23 @@ public function unsubscribeFromResponseHook(callable $function): void { $this->responseEvent->removeHandler($function); } + + /** + * Make an API call to the EasyPost API. + * + * This public, generic interface is useful for making arbitrary API calls to the EasyPost API that + * are not yet supported by the client library's services. When possible, the service for your use case + * should be used instead as it provides a more convenient and higher-level interface depending on the endpoint. + * + * @param string $method + * @param string $endpoint + * @param mixed $params + * @return mixed + */ + public function makeApiCall(string $method, string $endpoint, mixed $params = null): mixed + { + $response = Requestor::request($this, $method, $endpoint, $params); + + return InternalUtil::convertToEasyPostObject($this, $response); + } } diff --git a/test/EasyPost/EasyPostClientTest.php b/test/EasyPost/EasyPostClientTest.php index d8dc2dd2..02dc0c81 100644 --- a/test/EasyPost/EasyPostClientTest.php +++ b/test/EasyPost/EasyPostClientTest.php @@ -8,6 +8,22 @@ class EasyPostClientTest extends TestCase { + /** + * Setup the testing environment for this file. + */ + public static function setUpBeforeClass(): void + { + TestUtil::setupVcrTests(); + } + + /** + * Cleanup the testing environment once finished. + */ + public static function tearDownAfterClass(): void + { + TestUtil::teardownVcrTests(); + } + /** * Test setting and getting the API key for different EasyPostClients. */ @@ -66,4 +82,19 @@ public function testInvalidServiceProperty(): void ); } } + + /** + * Test making an API call using the generic makeApiCall method. + */ + public function testMakeApiCall(): void + { + TestUtil::setupCassette('client/makeApiCall.yml'); + + $client = new EasyPostClient((string)getenv('EASYPOST_TEST_API_KEY')); + + $response = $client->makeApiCall('get', '/addresses', ['page_size' => 1]); + + $this->assertCount(1, $response['addresses']); + $this->assertEquals('Address', $response['addresses'][0]['object']); + } } diff --git a/test/cassettes/client/makeApiCall.yml b/test/cassettes/client/makeApiCall.yml new file mode 100644 index 00000000..6b74982e --- /dev/null +++ b/test/cassettes/client/makeApiCall.yml @@ -0,0 +1,84 @@ + +- + request: + method: GET + url: 'https://api.easypost.com/v2/addresses?page_size=1' + headers: + Host: api.easypost.com + Accept-Encoding: '' + Accept: application/json + Authorization: '' + Content-Type: application/json + User-Agent: '' + 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: 16819987698e0e1fe787c81d011c5626 + cache-control: 'private, no-cache, no-store' + pragma: no-cache + expires: '0' + content-type: 'application/json; charset=utf-8' + content-length: '842' + x-runtime: '0.041143' + x-node: bigweb41nuq + x-version-label: easypost-202602121702-bfe72e7ac7-master + x-backend: easypost + x-proxied: ['intlb4nuq 0dcc3a6efb', 'extlb1nuq c01291cd8f'] + strict-transport-security: 'max-age=31536000; includeSubDomains; preload' + body: '{"addresses":[{"id":"adr_374a9a5ebc0511f094003cecef1b359e","object":"Address","created_at":"2025-11-07T18:11:43Z","updated_at":"2025-11-07T18:11:43Z","name":null,"company":"EASYPOST","street1":"000 UNKNOWN STREET","street2":null,"city":"NOT A CITY","state":"ZZ","zip":"00001","country":"US","phone":"","email":"","mode":"test","carrier_facility":null,"residential":null,"federal_tax_id":null,"state_tax_id":null,"verifications":{"zip4":{"success":true,"errors":[{"code":"E.ADDRESS.NOT_FOUND","field":"address","message":"Address not found","suggestion":null}],"details":null},"delivery":{"success":true,"errors":[{"code":"E.ADDRESS.NOT_FOUND","field":"address","message":"Address not found","suggestion":null}],"details":{"latitude":null,"longitude":null,"time_zone":null}},"verify_carrier":"ups"}}],"has_more":true}' + curl_info: + url: 'https://api.easypost.com/v2/addresses?page_size=1' + content_type: 'application/json; charset=utf-8' + http_code: 200 + header_size: 688 + request_size: 297 + filetime: -1 + ssl_verify_result: 0 + redirect_count: 0 + total_time: 0.226324 + namelookup_time: 0.005566 + connect_time: 0.063584 + pretransfer_time: 0.123707 + size_upload: 0.0 + size_download: 842.0 + speed_download: 3720.0 + speed_upload: 0.0 + download_content_length: 842.0 + upload_content_length: 0.0 + starttransfer_time: 0.226309 + redirect_time: 0.0 + redirect_url: '' + primary_ip: 169.62.110.131 + certinfo: { } + primary_port: 443 + local_ip: 10.130.6.22 + local_port: 52306 + http_version: 2 + protocol: 2 + ssl_verifyresult: 0 + scheme: https + appconnect_time_us: 123652 + queue_time_us: 24 + connect_time_us: 63584 + namelookup_time_us: 5566 + pretransfer_time_us: 123707 + redirect_time_us: 0 + starttransfer_time_us: 226309 + posttransfer_time_us: 123706 + total_time_us: 226324 + effective_method: GET + capath: '' + cainfo: '' + used_proxy: 0 + httpauth_used: 0 + proxyauth_used: 0 + conn_id: 0 + index: 0 From 646416653fa0f146b2d66b058dc411c8d695fc64 Mon Sep 17 00:00:00 2001 From: Justintime50 <39606064+Justintime50@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:54:44 -0700 Subject: [PATCH 2/2] chore: bump version --- CHANGELOG.md | 4 ++++ composer.json | 2 +- lib/EasyPost/Constant/Constants.php | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa239866..b12d7209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## v8.7.0 (2026-02-25) + +- Adds generic `makeApiCall` function + ## v8.6.0 (2026-02-20) - Adds the following functions: diff --git a/composer.json b/composer.json index 3b4fc193..5cea95c2 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "easypost/easypost-php", "description": "EasyPost Shipping API Client Library for PHP", - "version": "8.6.0", + "version": "8.7.0", "keywords": [ "shipping", "api", diff --git a/lib/EasyPost/Constant/Constants.php b/lib/EasyPost/Constant/Constants.php index 18b71e66..5c03b8cc 100644 --- a/lib/EasyPost/Constant/Constants.php +++ b/lib/EasyPost/Constant/Constants.php @@ -11,7 +11,7 @@ abstract class Constants const BETA_API_VERSION = 'beta'; // Library constants - const LIBRARY_VERSION = '8.6.0'; + const LIBRARY_VERSION = '8.7.0'; const SUPPORT_EMAIL = 'support@easypost.com'; // Validation