diff --git a/src/easypost.js b/src/easypost.js index 117137def..26fd8cf61 100644 --- a/src/easypost.js +++ b/src/easypost.js @@ -115,6 +115,23 @@ export default class EasyPostClient { this.responseHooks = []; } + /** + * 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 - The HTTP method to use (e.g. 'get', 'post', 'put', 'patch', 'del'). + * @param {string} endpoint - The API endpoint to call (e.g. '/addresses'). + * @param {Object} [params] - The parameters to send with the request. + * @returns {Promise} The response from the API call. + */ + async makeApiCall(method, endpoint, params = {}) { + const response = await this._request(endpoint, method, params); + + return response.body; + } + /** * Create a copy of an {@link EasyPostClient} with overridden options. * @param {EasyPostClient} client The `EasyPostClient` instance to clone. diff --git a/test/cassettes/EasyPost_3093958733/makes-an-API-call-using-the-generic-makeApiCall-method_2342601902/recording.har b/test/cassettes/EasyPost_3093958733/makes-an-API-call-using-the-generic-makeApiCall-method_2342601902/recording.har new file mode 100644 index 000000000..27359626b --- /dev/null +++ b/test/cassettes/EasyPost_3093958733/makes-an-API-call-using-the-generic-makeApiCall-method_2342601902/recording.har @@ -0,0 +1,159 @@ +{ + "log": { + "_recordingName": "EasyPost/makes an API call using the generic makeApiCall method", + "creator": { + "comment": "persister:fs", + "name": "Polly.JS", + "version": "6.0.6" + }, + "entries": [ + { + "_id": "834b8b7f362e8009ac3eac7fcad8be46", + "_order": 0, + "cache": {}, + "request": { + "bodySize": 0, + "cookies": [], + "headers": [ + { + "name": "accept-encoding", + "value": "gzip, deflate" + }, + { + "name": "accept", + "value": "application/json" + }, + { + "name": "content-type", + "value": "application/json" + }, + { + "name": "host", + "value": "api.easypost.com" + } + ], + "headersSize": 382, + "httpVersion": "HTTP/1.1", + "method": "GET", + "queryString": [ + { + "name": "page_size", + "value": "1" + } + ], + "url": "https://api.easypost.com/v2//addresses?page_size=1" + }, + "response": { + "bodySize": 608, + "content": { + "encoding": "base64", + "mimeType": "application/json; charset=utf-8", + "size": 608, + "text": "{\"addresses\":[{\"id\":\"adr_793e897dbc0611f08682ac1f6bc539ae\",\"object\":\"Address\",\"created_at\":\"2025-11-07T18:20:43Z\",\"updated_at\":\"2025-11-07T18:20: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}" + }, + "cookies": [], + "headers": [ + { + "name": "x-frame-options", + "value": "SAMEORIGIN" + }, + { + "name": "x-xss-protection", + "value": "1; mode=block" + }, + { + "name": "x-content-type-options", + "value": "nosniff" + }, + { + "name": "x-download-options", + "value": "noopen" + }, + { + "name": "x-permitted-cross-domain-policies", + "value": "none" + }, + { + "name": "referrer-policy", + "value": "strict-origin-when-cross-origin" + }, + { + "name": "x-ep-request-uuid", + "value": "16819983698e0f99e787ddc1011e7834" + }, + { + "name": "cache-control", + "value": "private, no-cache, no-store" + }, + { + "name": "pragma", + "value": "no-cache" + }, + { + "name": "expires", + "value": "0" + }, + { + "name": "content-type", + "value": "application/json; charset=utf-8" + }, + { + "name": "x-runtime", + "value": "0.036544" + }, + { + "name": "content-encoding", + "value": "gzip" + }, + { + "name": "transfer-encoding", + "value": "chunked" + }, + { + "name": "x-node", + "value": "bigweb56nuq" + }, + { + "name": "x-version-label", + "value": "easypost-202602121702-bfe72e7ac7-master" + }, + { + "name": "x-backend", + "value": "easypost" + }, + { + "name": "x-proxied", + "value": "intlb5nuq 0dcc3a6efb, extlb1nuq c01291cd8f" + }, + { + "name": "strict-transport-security", + "value": "max-age=31536000; includeSubDomains; preload" + }, + { + "name": "connection", + "value": "close" + } + ], + "headersSize": 710, + "httpVersion": "HTTP/1.1", + "redirectURL": "", + "status": 200, + "statusText": "OK" + }, + "startedDateTime": "2026-02-12T17:36:25.762Z", + "time": 278, + "timings": { + "blocked": -1, + "connect": -1, + "dns": -1, + "receive": 0, + "send": 0, + "ssl": -1, + "wait": 278 + } + } + ], + "pages": [], + "version": "1.2" + } +} diff --git a/test/services/easypost.test.js b/test/services/easypost.test.js index deee7abee..f726998af 100644 --- a/test/services/easypost.test.js +++ b/test/services/easypost.test.js @@ -147,4 +147,13 @@ describe('EasyPost', function () { expect(responseConfig1).to.be.null; expect(responseConfig2).to.be.null; }); + + it('makes an API call using the generic makeApiCall method', async function () { + const response = await client.makeApiCall('get', '/addresses', { + page_size: 1, + }); + + expect(response.addresses.length).to.equal(1); + expect(response.addresses[0].object).to.equal('Address'); + }); }); diff --git a/types/EasyPost.d.ts b/types/EasyPost.d.ts index 2d5af80bc..c65f60f7b 100644 --- a/types/EasyPost.d.ts +++ b/types/EasyPost.d.ts @@ -116,24 +116,42 @@ export default class EasyPost { * Adds a request hook to the EasyPost client. Useful for logging or debugging. */ public addRequestHook(fn: (config: IEasyPostRequest) => void): void; + /** * Removes a request hook from the EasyPost client. */ public removeRequestHook(fn: (config: IEasyPostRequest) => void): void; + /** * Clears all request hooks from the EasyPost client. */ public clearRequestHooks(): void; + /** * Adds a response hook to the EasyPost client. Useful for logging or debugging. */ public addResponseHook(fn: (config: IEasyPostResponse) => void): void; + /** * Removes a response hook from the EasyPost client. */ public removeResponseHook(fn: (config: IEasyPostResponse) => void): void; + /** * Clears all response hooks from the EasyPost client. */ public clearResponseHooks(): void; + + /** + * 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. + */ + public makeApiCall( + method: 'get' | 'post' | 'put' | 'patch' | 'del', + endpoint: string, + params?: Record, + ): Promise>; }