Repository: companieshouse/api-sdk-node
Pull request #774: LP-648 limited partner sdk changes
Author: login: vschot
Created: 2025-04-24T12:04:20Z | Merged: 2025-04-25T09:47:05Z

JIRA link
https://companieshouse.atlassian.net/browse/LP-648

Change description
Abstracted common fields for GP and limitedPartner fields
new interface for LimitedPartner
service functions for get, patch, delete, post limitedPartner
mocks + tests

Work checklist
 Tests added where applicable
 UI changes look good on mobile
 UI changes meet accessibility criteria
Merge instructions
We are committed to keeping commit history clean, consistent and linear. To achieve this commit should be structured as follows:

<type>[optional scope]: <description>
and contain the following structural elements:

fix: a commit that patches a bug in your codebase (this correlates with PATCH in semantic versioning),
feat: a commit that introduces a new feature to the codebase (this correlates with MINOR in semantic versioning),
BREAKING CHANGE: a commit that has a footer BREAKING CHANGE: introduces a breaking API change (correlating with MAJOR in semantic versioning). A BREAKING CHANGE can be part of commits of any type,
types other than fix: and feat: are allowed, for example build:, chore:, ci:, docs:, style:, refactor:, perf:, test:, and others,
footers other than BREAKING CHANGE: <description> may be provided.


Diff:
diff --git a/src/services/limited-partnerships/service.ts b/src/services/limited-partnerships/service.ts
index 389ec1e7..fca0a6fe 100644
--- a/src/services/limited-partnerships/service.ts
+++ b/src/services/limited-partnerships/service.ts
@@ -4,7 +4,8 @@ import {
     LimitedPartnership,
     LimitedPartnershipResourceCreated,
     LimitedPartnershipIncorporation,
-    GeneralPartner
+    GeneralPartner,
+    LimitedPartner
 } from "./types";
 import Resource, { ApiErrorResponse } from "../resource";
 
@@ -154,4 +155,73 @@ export default class LimitedPartnershipsService {
             resource: { ...response.body }
         };
     }
+
+    /*
+    * Calls to limited partner endpoints
+    */
+
+    public async postLimitedPartner (
+        transactionId: string,
+        body: LimitedPartner
+    ): Promise<Resource<LimitedPartnershipResourceCreated> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner`;
+        const response: HttpResponse = await this.client.httpPost(URL, body);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async getLimitedPartner (
+        transactionId: string,
+        limitedPartnerId: string
+    ): Promise<Resource<LimitedPartner> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner/${limitedPartnerId}`;
+        const response: HttpResponse = await this.client.httpGet(URL);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async getLimitedPartners (
+        transactionId: string
+    ): Promise<Resource<LimitedPartner[]> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partners`;
+        const response: HttpResponse = await this.client.httpGet(URL);
+
+        return {
+            httpStatusCode: response.status,
+            resource: response.body
+        };
+    }
+
+    public async patchLimitedPartner (
+        transactionId: string,
+        limitedPartnerId: string,
+        body: LimitedPartner["data"]
+    ): Promise<Resource<void> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner/${limitedPartnerId}`;
+        const response: HttpResponse = await this.client.httpPatch(URL, body);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async deleteLimitedPartner (
+        transactionId: string,
+        limitedPartnerId: string
+    ): Promise<Resource<void> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner/${limitedPartnerId}`;
+        const response: HttpResponse = await this.client.httpDelete(URL);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
 }
diff --git a/src/services/limited-partnerships/types.ts b/src/services/limited-partnerships/types.ts
index dacd0cc0..25c02258 100644
--- a/src/services/limited-partnerships/types.ts
+++ b/src/services/limited-partnerships/types.ts
@@ -28,31 +28,42 @@ export interface LimitedPartnership {
         sic_codes?: string[];
     };
 }
+type Partner = {
+    date_effective_from?: string;
+    date_of_birth?: string;
+    etag?: string;
+    forename?: string;
+    former_names?: string;
+    governing_law?: string;
+    kind?: string;
+    legal_entity_name?: string;
+    legal_entity_register_name?: string;
+    legal_entity_registration_location?: string;
+    legal_form?: string;
+    nationality1?: string;
+    nationality2?: string;
+    principal_office_address?: Address;
+    registered_company_number?: string;
+    resignation_date?: string;
+    surname?: string;
+    usual_residential_address?: Address;
+}
+
+export interface LimitedPartner {
+    id?: string;
+    data?: Partner & {
+        contribution_currency_type?: string,
+        contribution_currency_value?: string,
+        contribution_non_monetary_value?: string
+    };
+}
 
 export interface GeneralPartner {
     id?: string;
-    data?: {
-        date_effective_from?: string;
-        date_of_birth?: string;
-        etag?: string;
-        forename?: string;
-        former_names?: string;
-        governing_law?: string;
-        kind?: string;
-        legal_entity_name?: string;
-        legal_entity_register_name?: string;
-        legal_entity_registration_location?: string;
-        legal_form?: string;
-        nationality1?: string;
-        nationality2?: string;
+    data?: Partner & {
         not_disqualified_statement_checked?: boolean;
         legal_personality_statement_checked?: boolean;
-        principal_office_address?: Address;
-        registered_company_number?: string;
-        resignation_date?: string;
         service_address?: Address;
-        surname?: string;
-        usual_residential_address?: Address;
     };
 }
 
diff --git a/test/services/limited-partnerships/limited.partnerships.mock.ts b/test/services/limited-partnerships/limited.partnerships.mock.ts
index deda73fe..f84ac3c8 100644
--- a/test/services/limited-partnerships/limited.partnerships.mock.ts
+++ b/test/services/limited-partnerships/limited.partnerships.mock.ts
@@ -9,7 +9,8 @@ import {
     PartnershipType,
     Jurisdiction,
     Term,
-    GeneralPartner
+    GeneralPartner,
+    LimitedPartner
 } from "../../../src/services/limited-partnerships";
 
 export const requestClient = new RequestClient({
@@ -98,6 +99,49 @@ export const GENERAL_PARTNER_OBJECT_MOCK: GeneralPartner = {
     }
 };
 
+export const LIMITED_PARTNER_OBJECT_MOCK: LimitedPartner = {
+    id: "123456",
+    data: {
+        contribution_currency_type: "GBP",
+        contribution_currency_value: "1000",
+        contribution_non_monetary_value: "car",
+        date_effective_from: "2005-02-04",
+        date_of_birth: "2000-05-01",
+        etag: "",
+        forename: "John",
+        former_names: "Mary",
+        governing_law: "British Government",
+        kind: "",
+        legal_entity_name: "My company ltd",
+        legal_entity_register_name: "UK Register",
+        legal_entity_registration_location: "England",
+        legal_form: "abc",
+        nationality1: "English",
+        nationality2: "French",
+        principal_office_address: {
+            premises: "22",
+            address_line_1: "Some Street",
+            address_line_2: "Some Line 2",
+            locality: "Some Locality",
+            region: "Some Region",
+            country: "Some Country",
+            postal_code: "SC12 1WE"
+        },
+        registered_company_number: "223456",
+        resignation_date: "",
+        surname: "Doe",
+        usual_residential_address: {
+            premises: "25",
+            address_line_1: "That Street",
+            address_line_2: "That Line 2",
+            locality: "That Locality",
+            region: "That Region",
+            country: "That Country",
+            postal_code: "SC15 1N2"
+        }
+    }
+};
+
 // This structure is used when POSTing Incorporation data
 export const INCORPORATION_OBJECT_MOCK: Incorporation = {
     data: {
@@ -127,6 +171,7 @@ export const LIMITED_PARTNERSHIP_INCORPORATION_OBJECT_MOCK_WITH_SUB: LimitedPart
 export const TRANSACTION_ID = "12345";
 export const SUBMISSION_ID = "09876";
 export const GENERAL_PARTNER_ID = "00112233";
+export const LIMITED_PARTNER_ID = "11223344";
 export const LIMITED_PARTNERSHIP_ID = "00112233";
 export const FILE_RESOURCE_ID = "a1b2c3";
 export const UNAUTHORISED = "Unauthorised";
@@ -199,3 +244,33 @@ export const mockDeleteGeneralPartnerResponse = {
     404: { status: 404, body: { error: NOT_FOUND } },
     401: { status: 401, body: { error: UNAUTHORISED } }
 };
+
+export const mockPostLimitedPartnerResponse = {
+    201: { status: 201, body: mockLimitedPartnershipCreatedResource },
+    400: { status: 400, body: { error: BAD_REQUEST } },
+    401: { status: 401, body: { error: UNAUTHORISED } }
+};
+
+export const mockGetLimitedPartnerResponse = {
+    200: { status: 200, body: LIMITED_PARTNER_OBJECT_MOCK },
+    404: { status: 404, body: { error: NOT_FOUND } },
+    401: { status: 401, body: { error: UNAUTHORISED } }
+};
+
+export const mockGetLimitedPartnersResponse = {
+    200: { status: 200, body: [LIMITED_PARTNER_OBJECT_MOCK] },
+    404: { status: 404, body: { error: NOT_FOUND } },
+    401: { status: 401, body: { error: UNAUTHORISED } }
+};
+
+export const mockPatchLimitedPartnerResponse = {
+    200: { status: 200 },
+    400: { status: 400, body: { error: BAD_REQUEST } },
+    401: { status: 401, body: { error: UNAUTHORISED } }
+};
+
+export const mockDeleteLimitedPartnerResponse = {
+    204: { status: 204 },
+    404: { status: 404, body: { error: NOT_FOUND } },
+    401: { status: 401, body: { error: UNAUTHORISED } }
+};
diff --git a/test/services/limited-partnerships/limited.partnerships.spec.ts b/test/services/limited-partnerships/limited.partnerships.spec.ts
index 7f619095..7099cf04 100644
--- a/test/services/limited-partnerships/limited.partnerships.spec.ts
+++ b/test/services/limited-partnerships/limited.partnerships.spec.ts
@@ -9,7 +9,8 @@ import {
     LimitedPartnershipsService,
     LimitedPartnershipIncorporation,
     NameEndingType,
-    GeneralPartner
+    GeneralPartner,
+    LimitedPartner
 } from "../../../src/services/limited-partnerships";
 import Resource from "../../../src/services/resource";
 
@@ -676,4 +677,230 @@ describe("LimitedPartnershipsService", () => {
             expect(response.httpStatusCode).to.equal(204);
         });
     })
+
+    describe("LimitedPartner", () => {
+        describe("postLimitedPartner", () => {
+            it("should return object Id for postLimitedPartner method", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpPost")
+                    .resolves(mockValues.mockPostLimitedPartnerResponse[201]);
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+                const response = (await service.postLimitedPartner(
+                    mockValues.TRANSACTION_ID,
+                    mockValues.LIMITED_PARTNER_OBJECT_MOCK
+                )) as Resource<LimitedPartnershipResourceCreated>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partner",
+                        mockValues.LIMITED_PARTNER_OBJECT_MOCK
+                    )
+                ).to.be.true;
+
+                expect(response.httpStatusCode).to.equal(201);
+                expect(response.resource?.id).to.equal(
+                    mockValues.mockLimitedPartnershipCreatedResource.id
+                );
+            });
+
+            it("should return error 400 (Bad Request)", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpPost")
+                    .resolves(mockValues.mockPostLimitedPartnerResponse[400]);
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+                const response = (await service.postLimitedPartner(
+                    mockValues.TRANSACTION_ID,
+                    {}
+                )) as Resource<LimitedPartnershipResourceCreated>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partner",
+                        {}
+                    )
+                ).to.be.true;
+
+                expect(response.httpStatusCode).to.equal(400);
+            });
+        });
+
+        describe("getLimitedPartner", () => {
+            it("should return a status 200 and the limitedPartner object", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpGet")
+                    .resolves(mockValues.mockGetLimitedPartnerResponse[200]);
+
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+
+                const response = await service.getLimitedPartner(
+                    mockValues.TRANSACTION_ID,
+                    mockValues.SUBMISSION_ID
+                ) as Resource<LimitedPartner>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partner/09876"
+                    )
+                ).to.be.true;
+                expect(response.httpStatusCode).to.equal(200);
+                expect(response?.resource).to.eql(mockValues.LIMITED_PARTNER_OBJECT_MOCK);
+            });
+
+            it("should return error 401 (Unauthorised)", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpGet")
+                    .resolves(mockValues.mockGetLimitedPartnerResponse[401]);
+
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+                const response = (await service.getLimitedPartner(
+                    mockValues.TRANSACTION_ID,
+                    mockValues.SUBMISSION_ID
+                )) as Resource<any>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partner/09876"
+                    )
+                ).to.be.true;
+
+                expect(response.httpStatusCode).to.equal(401);
+                expect(response.resource.error).to.equal(mockValues.UNAUTHORISED);
+            });
+
+            it("should return error 404 (Not Found)", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpGet")
+                    .resolves(mockValues.mockGetLimitedPartnerResponse[404]);
+
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+                const response = (await service.getLimitedPartner(
+                    mockValues.TRANSACTION_ID,
+                    "wrong-id"
+                )) as Resource<any>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partner/wrong-id"
+                    )
+                ).to.be.true;
+
+                expect(response.httpStatusCode).to.equal(404);
+                expect(response.resource.error).to.equal(mockValues.NOT_FOUND);
+            });
+        })
+
+        describe("getLimitedPartners", () => {
+            it("should return a status 200 and the limitedPartner object", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpGet")
+                    .resolves(mockValues.mockGetLimitedPartnersResponse[200]);
+
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+
+                const response = await service.getLimitedPartners(
+                    mockValues.TRANSACTION_ID
+                ) as Resource<LimitedPartner>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partners"
+                    )
+                ).to.be.true;
+                expect(response.httpStatusCode).to.equal(200);
+                expect(response?.resource).to.eql([mockValues.LIMITED_PARTNER_OBJECT_MOCK]);
+            });
+        })
+
+        describe("patchLimitedPartner", () => {
+            it("should return 200 patchLimitedPartner method", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpPatch")
+                    .resolves(mockValues.mockPatchLimitedPartnerResponse[200]);
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+                const response = (await service.patchLimitedPartner(
+                    mockValues.TRANSACTION_ID,
+                    mockValues.LIMITED_PARTNER_ID,
+                    mockValues.LIMITED_PARTNER_OBJECT_MOCK.data
+                )) as Resource<void>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partner/11223344",
+                        mockValues.LIMITED_PARTNER_OBJECT_MOCK.data
+                    )
+                ).to.be.true;
+
+                expect(response.httpStatusCode).to.equal(200);
+            });
+
+            it("should return error 400 (Bad Request)", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpPatch")
+                    .resolves(mockValues.mockPatchLimitedPartnerResponse[400]);
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+                const response = (await service.patchLimitedPartner(
+                    mockValues.TRANSACTION_ID,
+                    mockValues.LIMITED_PARTNER_ID,
+                    {}
+                )) as Resource<LimitedPartnershipResourceCreated>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partner/11223344",
+                        {}
+                    )
+                ).to.be.true;
+
+                expect(response.httpStatusCode).to.equal(400);
+            });
+        })
+
+        describe("deleteLimitedPartner", () => {
+            it("should return 204 patchLimitedPartner method", async () => {
+                const mockRequest = sinon
+                    .stub(mockValues.requestClient, "httpDelete")
+                    .resolves(mockValues.mockDeleteLimitedPartnerResponse[204]);
+                const service = new LimitedPartnershipsService(
+                    mockValues.requestClient
+                );
+                const response = (await service.deleteLimitedPartner(
+                    mockValues.TRANSACTION_ID,
+                    mockValues.LIMITED_PARTNER_ID
+                )) as Resource<void>;
+
+                expect(mockRequest).to.have.been.calledOnce;
+                expect(
+                    mockRequest.calledWith(
+                        "/transactions/12345/limited-partnership/limited-partner/11223344"
+                    )
+                ).to.be.true;
+
+                expect(response.httpStatusCode).to.equal(204);
+            });
+        })
+    });
 });


Reviews:
user: login: lduranteau
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T13:30:10Z
user: login: vschot
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T13:47:02Z
user: login: lduranteau
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T15:09:23Z
user: login: lduranteau
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T15:09:52Z
user: login: vschot
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T16:45:09Z
user: login: lduranteau
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T07:04:56Z

Review comments:
diff_hunk: @@ -126,7 +170,7 @@ export const LIMITED_PARTNERSHIP_INCORPORATION_OBJECT_MOCK_WITH_SUB: LimitedPart
 
 export const TRANSACTION_ID = "12345";
 export const SUBMISSION_ID = "09876";
-export const GENERAL_PARTNER_ID = "00112233";
+export const PARTNER_ID = "00112233";
path: test/services/limited-partnerships/limited.partnerships.mock.ts
user: login: lduranteau
body: Keep GENERAL_PARTNER_ID and add another one for LIMITED_PARTNER_ID
it is better to have something explicit 
created_at: 2025-04-24T13:28:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -126,7 +170,7 @@ export const LIMITED_PARTNERSHIP_INCORPORATION_OBJECT_MOCK_WITH_SUB: LimitedPart
 
 export const TRANSACTION_ID = "12345";
 export const SUBMISSION_ID = "09876";
-export const GENERAL_PARTNER_ID = "00112233";
+export const PARTNER_ID = "00112233";
path: test/services/limited-partnerships/limited.partnerships.mock.ts
user: login: vschot
body: Done

created_at: 2025-04-24T13:47:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -154,4 +155,73 @@ export default class LimitedPartnershipsService {
             resource: { ...response.body }
         };
     }
+
+    /*
+    * Calls to limited partner endpoints
+    */
+
+    public async postLimitedPartner (
+        transactionId: string,
+        body: LimitedPartner
+    ): Promise<Resource<LimitedPartnershipResourceCreated> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner`;
+        const response: HttpResponse = await this.client.httpPost(URL, body);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async getLimitedPartner (
+        transactionId: string,
+        limitedPartnerId: string
+    ): Promise<Resource<LimitedPartner> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner/${limitedPartnerId}`;
+        const response: HttpResponse = await this.client.httpGet(URL);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async getLimitedPartners (
+        transactionId: string
+    ): Promise<Resource<LimitedPartner[]> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partners`;
+        const response: HttpResponse = await this.client.httpGet(URL, { transactionId });
path: src/services/limited-partnerships/service.ts
user: login: lduranteau
body: don't need transactionId in body
created_at: 2025-04-24T15:09:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -154,4 +155,73 @@ export default class LimitedPartnershipsService {
             resource: { ...response.body }
         };
     }
+
+    /*
+    * Calls to limited partner endpoints
+    */
+
+    public async postLimitedPartner (
+        transactionId: string,
+        body: LimitedPartner
+    ): Promise<Resource<LimitedPartnershipResourceCreated> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner`;
+        const response: HttpResponse = await this.client.httpPost(URL, body);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async getLimitedPartner (
+        transactionId: string,
+        limitedPartnerId: string
+    ): Promise<Resource<LimitedPartner> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner/${limitedPartnerId}`;
+        const response: HttpResponse = await this.client.httpGet(URL);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async getLimitedPartners (
+        transactionId: string
+    ): Promise<Resource<LimitedPartner[]> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partners`;
+        const response: HttpResponse = await this.client.httpGet(URL, { transactionId });
path: src/services/limited-partnerships/service.ts
user: login: lduranteau
body: don't need body at all
created_at: 2025-04-24T15:09:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -154,4 +155,73 @@ export default class LimitedPartnershipsService {
             resource: { ...response.body }
         };
     }
+
+    /*
+    * Calls to limited partner endpoints
+    */
+
+    public async postLimitedPartner (
+        transactionId: string,
+        body: LimitedPartner
+    ): Promise<Resource<LimitedPartnershipResourceCreated> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner`;
+        const response: HttpResponse = await this.client.httpPost(URL, body);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async getLimitedPartner (
+        transactionId: string,
+        limitedPartnerId: string
+    ): Promise<Resource<LimitedPartner> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partner/${limitedPartnerId}`;
+        const response: HttpResponse = await this.client.httpGet(URL);
+
+        return {
+            httpStatusCode: response.status,
+            resource: { ...response.body }
+        };
+    }
+
+    public async getLimitedPartners (
+        transactionId: string
+    ): Promise<Resource<LimitedPartner[]> | ApiErrorResponse> {
+        const URL = `/transactions/${transactionId}/limited-partnership/limited-partners`;
+        const response: HttpResponse = await this.client.httpGet(URL, { transactionId });
path: src/services/limited-partnerships/service.ts
user: login: vschot
body: Done
created_at: 2025-04-24T16:45:08Z
author_association: CONTRIBUTOR

PR comments:
user: login: chsonarqubeprchecks[bot]
created_at: 2025-04-24T16:49:21Z
body: **SonarQube Quality Gate**

[![Quality Gate passed](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](http://code-analysis.platform.aws.chdev.org:9000/dashboard?id=api-sdk-node&pullRequest=774)

[![Bug](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/common/bug-16px.png 'Bug')](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=BUG) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/checks/RatingBadge/A-16px.png 'A')](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=BUG) [0 Bugs](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=BUG)  
[![Vulnerability](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/common/vulnerability-16px.png 'Vulnerability')](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=VULNERABILITY) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/checks/RatingBadge/A-16px.png 'A')](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/common/security_hotspot-16px.png 'Security Hotspot')](http://code-analysis.platform.aws.chdev.org:9000/security_hotspots?id=api-sdk-node&pullRequest=774) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/checks/RatingBadge/A-16px.png 'A')](http://code-analysis.platform.aws.chdev.org:9000/security_hotspots?id=api-sdk-node&pullRequest=774) [0 Security Hotspots](http://code-analysis.platform.aws.chdev.org:9000/security_hotspots?id=api-sdk-node&pullRequest=774)  
[![Code Smell](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/common/code_smell-16px.png 'Code Smell')](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=CODE_SMELL) [![A](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/checks/RatingBadge/A-16px.png 'A')](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=CODE_SMELL) [0 Code Smells](http://code-analysis.platform.aws.chdev.org:9000/project/issues?id=api-sdk-node&pullRequest=774&resolved=false&types=CODE_SMELL)

[![100.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/checks/CoverageChart/100-16px.png '100.0%')](http://code-analysis.platform.aws.chdev.org:9000/component_measures?id=api-sdk-node&pullRequest=774&metric=new_coverage&view=list) [100.0% Coverage](http://code-analysis.platform.aws.chdev.org:9000/component_measures?id=api-sdk-node&pullRequest=774&metric=new_coverage&view=list)  
[![0.0%](https://raw.githubusercontent.com/SonarSource/sonarqube-static-resources/master/v86/checks/Duplications/3-16px.png '0.0%')](http://code-analysis.platform.aws.chdev.org:9000/component_measures?id=api-sdk-node&pullRequest=774&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](http://code-analysis.platform.aws.chdev.org:9000/component_measures?id=api-sdk-node&pullRequest=774&metric=new_duplicated_lines_density&view=list)


author_association: NONE