Repository: calcom/cal.com
Pull request #21359: feat: v2 managed organizations pagination
Author: login: supalarry
Labels: name: ✨ feature
description: New feature or request
name: platform
description: Anything related to our platform plan
name: organizations
description: area: organizations, orgs
name: core
description: area: core, team members only
name: ready-for-e2e
Created: 2025-05-16T14:24:08Z | Merged: 2025-05-27T10:50:31Z

Linear [CAL-5293](https://linear.app/calcom/issue/CAL-5293/feat-v2-managed-organizations-pagination)
    
<!-- This is an auto-generated description by mrge. -->
---

## Summary by mrge
Added pagination support to the managed organizations API and introduced a shared pagination helper for consistent pagination metadata.

- **New Features**
  - Managed organizations endpoints now accept `skip` and `take` query parameters and return pagination info.
  - Added a shared `getPagination` helper and unified pagination types across the API.

<!-- End of auto-generated description by mrge. -->




Diff:
diff --git a/apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts b/apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
index c1b16737a5d24a..5bebe6abd1e7c2 100644
--- a/apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
+++ b/apps/api/v2/src/ee/bookings/2024-08-13/services/bookings.service.ts
@@ -5,6 +5,7 @@ import { InputBookingsService_2024_08_13 } from "@/ee/bookings/2024-08-13/servic
 import { OutputBookingsService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/output.service";
 import { PlatformBookingsService } from "@/ee/bookings/shared/platform-bookings.service";
 import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.repository";
+import { getPagination } from "@/lib/pagination/pagination";
 import { BillingService } from "@/modules/billing/services/billing.service";
 import { BookingSeatRepository } from "@/modules/booking-seat/booking-seat.repository";
 import { KyselyReadService } from "@/modules/kysely/kysely-read.service";
@@ -538,10 +539,13 @@ export class BookingsService_2024_08_13 {
       queryParams.attendeeEmail = await this.getAttendeeEmail(queryParams.attendeeEmail, user);
     }
 
+    const skip = Math.abs(queryParams?.skip ?? 0);
+    const take = Math.abs(queryParams?.take ?? 100);
+
     const fetchedBookings: { bookings: { id: number }[]; totalCount: number } = await getAllUserBookings({
       bookingListingByStatus: queryParams.status || [],
-      skip: queryParams.skip ?? 0,
-      take: queryParams.take ?? 100,
+      skip,
+      take,
       filters: {
         ...this.inputService.transformGetBookingsFilters(queryParams),
         ...(userIds?.length ? { userIds } : {}),
@@ -594,28 +598,11 @@ export class BookingsService_2024_08_13 {
       }
     }
 
-    const skip = Math.abs(queryParams?.skip ?? 0);
-    const take = Math.abs(queryParams?.take ?? 100);
-    const itemsPerPage = take;
-    const totalPages = itemsPerPage !== 0 ? Math.ceil(fetchedBookings.totalCount / itemsPerPage) : 0;
-    const currentPage = Math.floor(skip / itemsPerPage) + 1;
-    const hasNextPage = skip + itemsPerPage < fetchedBookings.totalCount;
-    const hasPreviousPage = skip > 0;
+    const pagination = getPagination({ skip, take, totalCount: fetchedBookings.totalCount });
+
     return {
       bookings: formattedBookings,
-      pagination: {
-        totalItems: fetchedBookings.totalCount,
-        // clamp remainingItems between 0 and totalCount
-        remainingItems: Math.min(
-          Math.max(fetchedBookings.totalCount - (skip + take), 0),
-          fetchedBookings.totalCount
-        ),
-        itemsPerPage: itemsPerPage,
-        currentPage: currentPage,
-        totalPages: totalPages,
-        hasNextPage: hasNextPage,
-        hasPreviousPage: hasPreviousPage,
-      },
+      pagination,
     };
   }
 
diff --git a/apps/api/v2/src/lib/pagination/pagination.spec.ts b/apps/api/v2/src/lib/pagination/pagination.spec.ts
new file mode 100644
index 00000000000000..6d44860bdc0e06
--- /dev/null
+++ b/apps/api/v2/src/lib/pagination/pagination.spec.ts
@@ -0,0 +1,101 @@
+import { getPagination, clamp } from "./pagination";
+
+describe("getPagination", () => {
+  it("handles the first page correctly", () => {
+    const pagination = getPagination({ skip: 0, take: 10, totalCount: 35 });
+    expect(pagination).toEqual({
+      returnedItems: 10,
+      totalItems: 35,
+      itemsPerPage: 10,
+      remainingItems: 25,
+      currentPage: 1,
+      totalPages: 4,
+      hasNextPage: true,
+      hasPreviousPage: false,
+    });
+  });
+
+  it("handles a middle page correctly", () => {
+    const pagination = getPagination({ skip: 10, take: 10, totalCount: 35 });
+    expect(pagination).toEqual({
+      returnedItems: 10,
+      totalItems: 35,
+      itemsPerPage: 10,
+      remainingItems: 15,
+      currentPage: 2,
+      totalPages: 4,
+      hasNextPage: true,
+      hasPreviousPage: true,
+    });
+  });
+
+  it("handles the last page when it is not completely full", () => {
+    const pagination = getPagination({ skip: 30, take: 10, totalCount: 35 });
+    expect(pagination).toEqual({
+      returnedItems: 5,
+      totalItems: 35,
+      itemsPerPage: 10,
+      remainingItems: 0,
+      currentPage: 4,
+      totalPages: 4,
+      hasNextPage: false,
+      hasPreviousPage: true,
+    });
+  });
+
+  it("clamps skip values that exceed the total item count", () => {
+    const pagination = getPagination({ skip: 40, take: 10, totalCount: 35 });
+    expect(pagination).toEqual({
+      returnedItems: 0,
+      totalItems: 35,
+      itemsPerPage: 10,
+      remainingItems: 0,
+      currentPage: 4,
+      totalPages: 4,
+      hasNextPage: false,
+      hasPreviousPage: true,
+    });
+  });
+
+  it("works when itemsPerPage (take) is zero", () => {
+    const pagination = getPagination({ skip: 0, take: 0, totalCount: 35 });
+    expect(pagination).toEqual({
+      returnedItems: 0,
+      totalItems: 35,
+      itemsPerPage: 0,
+      remainingItems: 35,
+      currentPage: 0,
+      totalPages: 0,
+      hasNextPage: true,
+      hasPreviousPage: false,
+    });
+  });
+
+  it("works when the collection is empty", () => {
+    const pagination = getPagination({ skip: 0, take: 10, totalCount: 0 });
+    expect(pagination).toEqual({
+      returnedItems: 0,
+      totalItems: 0,
+      itemsPerPage: 10,
+      remainingItems: 0,
+      currentPage: 0,
+      totalPages: 0,
+      hasNextPage: false,
+      hasPreviousPage: false,
+    });
+  });
+});
+
+describe("clamp", () => {
+  it("returns the value unchanged when it is inside the range", () => {
+    expect(clamp({ value: 5, min: 1, max: 10 })).toBe(5);
+  });
+
+  it("clamps values below the minimum", () => {
+    expect(clamp({ value: -3, min: 0, max: 10 })).toBe(0);
+  });
+
+  it("clamps values above the maximum", () => {
+    expect(clamp({ value: 42, min: 0, max: 10 })).toBe(10);
+  });
+});
diff --git a/apps/api/v2/src/lib/pagination/pagination.ts b/apps/api/v2/src/lib/pagination/pagination.ts
new file mode 100644
index 00000000000000..61a564f8f702c5
--- /dev/null
+++ b/apps/api/v2/src/lib/pagination/pagination.ts
@@ -0,0 +1,78 @@
+import { PaginationMetaDto } from "@calcom/platform-types";
+
+type Pagination = {
+  skip: number;
+  take: number;
+  totalCount: number;
+};
+
+export function getPagination(pagination: Pagination): PaginationMetaDto {
+  const { skip, take, totalCount } = pagination;
+
+  const safeSkip = clamp({ value: skip, min: 0, max: totalCount });
+  const itemsPerPage = take;
+  const remainingItems = getRemainingItems(safeSkip, itemsPerPage, totalCount);
+  const totalPages = getTotalPages(itemsPerPage, totalCount);
+  const currentPage = getCurrentPage(safeSkip, itemsPerPage, totalPages);
+  const hasNextPage = getHasNextPage(safeSkip, itemsPerPage, totalCount);
+  const hasPreviousPage = getHasPreviousPage(safeSkip);
+  const returnedItems = getReturnedItems(safeSkip, itemsPerPage, totalCount);
+
+  return {
+    returnedItems,
+    totalItems: totalCount,
+    itemsPerPage,
+    remainingItems,
+    currentPage,
+    totalPages,
+    hasNextPage,
+    hasPreviousPage,
+  };
+}
+
+function getRemainingItems(skip: number, itemsPerPage: number, totalCount: number) {
+  return clamp({
+    value: totalCount - (skip + itemsPerPage),
+    min: 0,
+    max: totalCount,
+  });
+}
+
+function getTotalPages(itemsPerPage: number, totalCount: number) {
+  return itemsPerPage !== 0 ? Math.ceil(totalCount / itemsPerPage) : 0;
+}
+
+function getCurrentPage(skip: number, itemsPerPage: number, totalPages: number) {
+  const rawCurrentPage = Math.floor(skip / itemsPerPage) + 1;
+  if (totalPages === 0) {
+    return 0;
+  }
+  return clamp({ value: rawCurrentPage, min: 1, max: totalPages });
+}
+
+function getHasNextPage(skip: number, itemsPerPage: number, totalCount: number) {
+  return skip + itemsPerPage < totalCount;
+}
+
+function getHasPreviousPage(skip: number) {
+  return skip > 0;
+}
+
+function getReturnedItems(skip: number, itemsPerPage: number, totalCount: number) {
+  const remaining = totalCount - skip;
+  return clamp({
+    value: remaining,
+    min: 0,
+    max: itemsPerPage,
+  });
+}
+
+type ClampArgs = {
+  value: number;
+  min: number;
+  max: number;
+};
+
+export function clamp({ value, min, max }: ClampArgs): number {
+  return Math.max(min, Math.min(value, max));
+}
diff --git a/apps/api/v2/src/modules/organizations/organizations/managed-organizations.repository.ts b/apps/api/v2/src/modules/organizations/organizations/managed-organizations.repository.ts
index e859dd3cf06957..4d4aeef114333b 100644
--- a/apps/api/v2/src/modules/organizations/organizations/managed-organizations.repository.ts
+++ b/apps/api/v2/src/modules/organizations/organizations/managed-organizations.repository.ts
@@ -2,6 +2,7 @@ import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
 import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
 import { Injectable } from "@nestjs/common";
 
+import { SkipTakePagination } from "@calcom/platform-types";
 import { Prisma } from "@calcom/prisma/client";
 
 @Injectable()
@@ -34,11 +35,26 @@ export class ManagedOrganizationsRepository {
     });
   }
 
-  async getByManagerOrganizationId(managerOrganizationId: number) {
-    return this.dbRead.prisma.managedOrganization.findMany({
-      where: {
-        managerOrganizationId,
-      },
-    });
+  async getByManagerOrganizationIdPaginated(managerOrganizationId: number, pagination: SkipTakePagination) {
+    const { skip, take } = pagination;
+
+    const where: Prisma.ManagedOrganizationWhereInput = {
+      managerOrganizationId,
+    };
+
+    const [totalItems, linkRows] = await this.dbRead.prisma.$transaction([
+      this.dbRead.prisma.managedOrganization.count({ where }),
+      this.dbRead.prisma.managedOrganization.findMany({
+        where,
+        skip,
+        take,
+        orderBy: { managedOrganizationId: "asc" },
+        include: { managedOrganization: true },
+      }),
+    ]);
+
+    const items = linkRows.map((l) => l.managedOrganization);
+
+    return { totalItems, items };
   }
 }
diff --git a/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.controller.e2e-spec.ts b/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.controller.e2e-spec.ts
index 0e3a43f1a2f9fd..a2186d3d620a5e 100644
--- a/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.controller.e2e-spec.ts
+++ b/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.controller.e2e-spec.ts
@@ -7,6 +7,7 @@ import { CreateOAuthClientResponseDto } from "@/modules/oauth-clients/controller
 import { GetOAuthClientResponseDto } from "@/modules/oauth-clients/controllers/oauth-clients/responses/GetOAuthClientResponse.dto";
 import { CreateOrganizationInput } from "@/modules/organizations/organizations/inputs/create-managed-organization.input";
 import { UpdateOrganizationInput } from "@/modules/organizations/organizations/inputs/update-managed-organization.input";
+import { GetManagedOrganizationsOutput } from "@/modules/organizations/organizations/outputs/get-managed-organizations.output";
 import {
   ManagedOrganizationWithApiKeyOutput,
   ManagedOrganizationOutput,
@@ -304,7 +305,7 @@ describe("Organizations Organizations Endpoints", () => {
       .set("Authorization", `Bearer ${managerOrgAdminApiKey}`)
       .expect(200)
       .then(async (response) => {
-        const responseBody: ApiSuccessResponse<ManagedOrganizationOutput[]> = response.body;
+        const responseBody: GetManagedOrganizationsOutput = response.body;
         expect(responseBody.status).toEqual(SUCCESS_STATUS);
         const responseManagedOrgs = responseBody.data;
         expect(responseManagedOrgs?.length).toEqual(1);
@@ -312,6 +313,14 @@ describe("Organizations Organizations Endpoints", () => {
         expect(responseManagedOrg?.id).toBeDefined();
         expect(responseManagedOrg?.name).toEqual(managedOrg.name);
         expect(responseManagedOrg?.metadata).toEqual(managedOrg.metadata);
+
+        expect(responseBody.pagination).toBeDefined();
+        expect(responseBody.pagination.totalItems).toEqual(1);
+        expect(responseBody.pagination.remainingItems).toEqual(0);
+        expect(responseBody.pagination.returnedItems).toEqual(1);
+        expect(responseBody.pagination.itemsPerPage).toEqual(250);
+        expect(responseBody.pagination.currentPage).toEqual(1);
+        expect(responseBody.pagination.totalPages).toEqual(1);
       });
   });
 
diff --git a/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.controller.ts b/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.controller.ts
index 1e2bb3e5123888..0f811c499b0a20 100644
--- a/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.controller.ts
+++ b/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.controller.ts
@@ -28,10 +28,12 @@ import {
   HttpCode,
   HttpStatus,
   Delete,
+  Query,
 } from "@nestjs/common";
 import { ApiHeader, ApiOperation, ApiTags as DocsTags } from "@nestjs/swagger";
 
 import { SUCCESS_STATUS } from "@calcom/platform-constants";
+import { SkipTakePagination } from "@calcom/platform-types";
 
 const SCALE = "SCALE";
 
@@ -99,14 +101,15 @@ export class OrganizationsOrganizationsController {
       "Requires the user to have at least the 'ORG_ADMIN' role within the organization. Additionally, for platform, the plan must be 'SCALE' or higher to access this endpoint.",
   })
   async getOrganizations(
-    @Param("orgId", ParseIntPipe) managerOrganizationId: number
+    @Param("orgId", ParseIntPipe) managerOrganizationId: number,
+    @Query() queryPagination: SkipTakePagination
   ): Promise<GetManagedOrganizationsOutput> {
-    const organizations = await this.managedOrganizationsService.getManagedOrganizations(
-      managerOrganizationId
-    );
+    const { organizations, pagination: responsePagination } =
+      await this.managedOrganizationsService.getManagedOrganizations(managerOrganizationId, queryPagination);
     return {
       status: SUCCESS_STATUS,
       data: organizations,
+      pagination: responsePagination,
     };
   }
 
diff --git a/apps/api/v2/src/modules/organizations/organizations/outputs/get-managed-organizations.output.ts b/apps/api/v2/src/modules/organizations/organizations/outputs/get-managed-organizations.output.ts
index e063bcbe5dea10..cf52f8d674acd8 100644
--- a/apps/api/v2/src/modules/organizations/organizations/outputs/get-managed-organizations.output.ts
+++ b/apps/api/v2/src/modules/organizations/organizations/outputs/get-managed-organizations.output.ts
@@ -4,6 +4,7 @@ import { Expose, Type } from "class-transformer";
 import { IsEnum, ValidateNested } from "class-validator";
 
 import { ERROR_STATUS, SUCCESS_STATUS } from "@calcom/platform-constants";
+import { PaginationMetaDto } from "@calcom/platform-types";
 
 export class GetManagedOrganizationsOutput {
   @ApiProperty({ example: SUCCESS_STATUS, enum: [SUCCESS_STATUS, ERROR_STATUS] })
@@ -17,4 +18,9 @@ export class GetManagedOrganizationsOutput {
   @ValidateNested({ each: true })
   @Type(() => ManagedOrganizationOutput)
   data!: ManagedOrganizationOutput[];
+
+  @ApiProperty({ type: () => PaginationMetaDto })
+  @Type(() => PaginationMetaDto)
+  @ValidateNested()
+  pagination!: PaginationMetaDto;
 }
diff --git a/apps/api/v2/src/modules/organizations/organizations/services/managed-organizations.service.ts b/apps/api/v2/src/modules/organizations/organizations/services/managed-organizations.service.ts
index f4a917c3b0618f..cd818681516d8f 100644
--- a/apps/api/v2/src/modules/organizations/organizations/services/managed-organizations.service.ts
+++ b/apps/api/v2/src/modules/organizations/organizations/services/managed-organizations.service.ts
@@ -1,3 +1,4 @@
+import { getPagination } from "@/lib/pagination/pagination";
 import { ApiKeysService } from "@/modules/api-keys/services/api-keys.service";
 import { ApiAuthGuardUser } from "@/modules/auth/strategies/api-auth/api-auth.strategy";
 import { ManagedOrganizationsBillingService } from "@/modules/billing/services/managed-organizations.billing.service";
@@ -11,6 +12,7 @@ import { ProfilesRepository } from "@/modules/profiles/profiles.repository";
 import { ForbiddenException, Injectable, NotFoundException } from "@nestjs/common";
 
 import { slugify } from "@calcom/platform-libraries";
+import { SkipTakePagination } from "@calcom/platform-types";
 
 @Injectable()
 export class ManagedOrganizationsService {
@@ -99,18 +101,22 @@ export class ManagedOrganizationsService {
     return this.managedOrganizationsOutputService.getOutputManagedOrganization(organization);
   }
 
-  async getManagedOrganizations(managerOrganizationId: number) {
-    const managedOrganizations = await this.managedOrganizationsRepository.getByManagerOrganizationId(
-      managerOrganizationId
-    );
-    const managedOrganizationsIds = managedOrganizations.map(
-      (managedOrganization) => managedOrganization.managedOrganizationId
-    );
+  async getManagedOrganizations(managerOrganizationId: number, pagination: SkipTakePagination) {
+    const { items: managedOrganizations, totalItems } =
+      await this.managedOrganizationsRepository.getByManagerOrganizationIdPaginated(
+        managerOrganizationId,
+        pagination
+      );
 
-    const organizations = await this.organizationsRepository.findByIds(managedOrganizationsIds);
-    return organizations.map((organization) =>
-      this.managedOrganizationsOutputService.getOutputManagedOrganization(organization)
-    );
+    return {
+      organizations: managedOrganizations.map((managedOrganization) =>
+        this.managedOrganizationsOutputService.getOutputManagedOrganization(managedOrganization)
+      ),
+      pagination: getPagination({
+        ...pagination,
+        totalCount: totalItems,
+      }),
+    };
   }
 
   async updateManagedOrganization(managedOrganizationId: number, body: UpdateOrganizationInput) {
diff --git a/apps/api/v2/swagger/documentation.json b/apps/api/v2/swagger/documentation.json
index 6c614762a7209f..7e36b9b43f62a3 100644
--- a/apps/api/v2/swagger/documentation.json
+++ b/apps/api/v2/swagger/documentation.json
@@ -446,9 +446,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -456,9 +459,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -654,9 +659,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -664,9 +672,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -1938,9 +1948,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -1948,9 +1961,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -2639,9 +2654,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -2649,9 +2667,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -2717,9 +2737,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -2727,9 +2750,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -2861,9 +2886,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -2871,9 +2899,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -4195,9 +4225,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -4205,9 +4238,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -4281,9 +4316,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -4291,9 +4329,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -5695,9 +5735,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -5705,9 +5748,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -5971,9 +6016,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -5981,9 +6029,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -6408,9 +6458,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -6418,9 +6471,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -8771,9 +8826,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -8781,9 +8839,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -9042,6 +9102,31 @@
             "schema": {
               "type": "number"
             }
+          },
+          {
+            "name": "take",
+            "required": false,
+            "in": "query",
+            "description": "Maximum number of items to return",
+            "example": 25,
+            "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
+              "type": "number"
+            }
+          },
+          {
+            "name": "skip",
+            "required": false,
+            "in": "query",
+            "description": "Number of items to skip",
+            "example": 0,
+            "schema": {
+              "minimum": 0,
+              "default": 0,
+              "type": "number"
+            }
           }
         ],
         "responses": {
@@ -9700,9 +9785,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -9710,9 +9798,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -9760,9 +9850,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -9770,9 +9863,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -11603,9 +11698,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -11613,9 +11711,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -11992,9 +12092,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -12002,9 +12105,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -12052,9 +12157,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -12062,9 +12170,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -12372,9 +12482,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -12382,9 +12495,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -12424,9 +12539,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -12434,9 +12552,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -12606,9 +12726,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -12616,9 +12739,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -21998,6 +22123,66 @@
           "data"
         ]
       },
+      "PaginationMetaDto": {
+        "type": "object",
+        "properties": {
+          "totalItems": {
+            "type": "number",
+            "description": "The total number of items available across all pages, matching the query criteria.",
+            "example": 123,
+            "minimum": 0
+          },
+          "remainingItems": {
+            "type": "number",
+            "description": "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
+            "example": 103,
+            "minimum": 0
+          },
+          "returnedItems": {
+            "type": "number",
+            "description": "The number of items returned in the current page.",
+            "example": 10
+          },
+          "itemsPerPage": {
+            "type": "number",
+            "description": "The maximum number of items requested per page.",
+            "example": 10,
+            "minimum": 1
+          },
+          "currentPage": {
+            "type": "number",
+            "description": "The current page number being returned.",
+            "example": 2,
+            "minimum": 1
+          },
+          "totalPages": {
+            "type": "number",
+            "description": "The total number of pages available.",
+            "example": 13,
+            "minimum": 0
+          },
+          "hasNextPage": {
+            "type": "boolean",
+            "description": "Indicates if there is a subsequent page available after the current one.",
+            "example": true
+          },
+          "hasPreviousPage": {
+            "type": "boolean",
+            "description": "Indicates if there is a preceding page available before the current one.",
+            "example": true
+          }
+        },
+        "required": [
+          "totalItems",
+          "remainingItems",
+          "returnedItems",
+          "itemsPerPage",
+          "currentPage",
+          "totalPages",
+          "hasNextPage",
+          "hasPreviousPage"
+        ]
+      },
       "GetManagedOrganizationsOutput": {
         "type": "object",
         "properties": {
@@ -22014,11 +22199,15 @@
             "items": {
               "$ref": "#/components/schemas/ManagedOrganizationOutput"
             }
+          },
+          "pagination": {
+            "$ref": "#/components/schemas/PaginationMetaDto"
           }
         },
         "required": [
           "status",
-          "data"
+          "data",
+          "pagination"
         ]
       },
       "UpdateOrganizationInput": {
@@ -24205,60 +24394,6 @@
           "data"
         ]
       },
-      "PaginationMetaDto": {
-        "type": "object",
-        "properties": {
-          "totalItems": {
-            "type": "number",
-            "minimum": 0,
-            "description": "The total number of items available across all pages, matching the query criteria.",
-            "example": 123
-          },
-          "remainingItems": {
-            "type": "number",
-            "minimum": 0,
-            "description": "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
-            "example": 103
-          },
-          "itemsPerPage": {
-            "type": "number",
-            "minimum": 1,
-            "description": "The maximum number of items requested per page.",
-            "example": 10
-          },
-          "currentPage": {
-            "type": "number",
-            "minimum": 1,
-            "description": "The current page number being returned.",
-            "example": 2
-          },
-          "totalPages": {
-            "type": "number",
-            "minimum": 0,
-            "description": "The total number of pages available.",
-            "example": 13
-          },
-          "hasNextPage": {
-            "type": "boolean",
-            "description": "Indicates if there is a subsequent page available after the current one.",
-            "example": true
-          },
-          "hasPreviousPage": {
-            "type": "boolean",
-            "description": "Indicates if there is a preceding page available before the current one.",
-            "example": true
-          }
-        },
-        "required": [
-          "totalItems",
-          "remainingItems",
-          "itemsPerPage",
-          "currentPage",
-          "totalPages",
-          "hasNextPage",
-          "hasPreviousPage"
-        ]
-      },
       "GetBookingsOutput_2024_08_13": {
         "type": "object",
         "properties": {
diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json
index b18c8df9525e68..a005beaa7d498f 100644
--- a/docs/api-reference/v2/openapi.json
+++ b/docs/api-reference/v2/openapi.json
@@ -430,9 +430,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -440,9 +443,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -628,9 +633,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -638,9 +646,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -1860,9 +1870,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -1870,9 +1883,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -2533,9 +2548,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -2543,9 +2561,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -2609,9 +2629,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -2619,9 +2642,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -2749,9 +2774,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -2759,9 +2787,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -4011,9 +4041,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -4021,9 +4054,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -4095,9 +4130,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -4105,9 +4143,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -5447,9 +5487,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -5457,9 +5500,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -5709,9 +5754,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -5719,9 +5767,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -6128,9 +6178,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -6138,9 +6191,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -8358,9 +8413,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -8368,9 +8426,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -8617,6 +8677,31 @@
             "schema": {
               "type": "number"
             }
+          },
+          {
+            "name": "take",
+            "required": false,
+            "in": "query",
+            "description": "Maximum number of items to return",
+            "example": 25,
+            "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
+              "type": "number"
+            }
+          },
+          {
+            "name": "skip",
+            "required": false,
+            "in": "query",
+            "description": "Number of items to skip",
+            "example": 0,
+            "schema": {
+              "minimum": 0,
+              "default": 0,
+              "type": "number"
+            }
           }
         ],
         "responses": {
@@ -9245,9 +9330,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -9255,9 +9343,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -9303,9 +9393,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -9313,9 +9406,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -11073,9 +11168,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -11083,9 +11181,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -11446,9 +11546,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -11456,9 +11559,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -11504,9 +11609,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -11514,9 +11622,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -11810,9 +11920,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -11820,9 +11933,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -11860,9 +11975,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -11870,9 +11988,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           },
@@ -12034,9 +12154,12 @@
             "name": "take",
             "required": false,
             "in": "query",
-            "description": "The number of items to return",
-            "example": 10,
+            "description": "Maximum number of items to return",
+            "example": 25,
             "schema": {
+              "minimum": 1,
+              "maximum": 250,
+              "default": 250,
               "type": "number"
             }
           },
@@ -12044,9 +12167,11 @@
             "name": "skip",
             "required": false,
             "in": "query",
-            "description": "The number of items to skip",
+            "description": "Number of items to skip",
             "example": 0,
             "schema": {
+              "minimum": 0,
+              "default": 0,
               "type": "number"
             }
           }
@@ -20158,6 +20283,66 @@
         },
         "required": ["status", "data"]
       },
+      "PaginationMetaDto": {
+        "type": "object",
+        "properties": {
+          "totalItems": {
+            "type": "number",
+            "description": "The total number of items available across all pages, matching the query criteria.",
+            "example": 123,
+            "minimum": 0
+          },
+          "remainingItems": {
+            "type": "number",
+            "description": "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
+            "example": 103,
+            "minimum": 0
+          },
+          "returnedItems": {
+            "type": "number",
+            "description": "The number of items returned in the current page.",
+            "example": 10
+          },
+          "itemsPerPage": {
+            "type": "number",
+            "description": "The maximum number of items requested per page.",
+            "example": 10,
+            "minimum": 1
+          },
+          "currentPage": {
+            "type": "number",
+            "description": "The current page number being returned.",
+            "example": 2,
+            "minimum": 1
+          },
+          "totalPages": {
+            "type": "number",
+            "description": "The total number of pages available.",
+            "example": 13,
+            "minimum": 0
+          },
+          "hasNextPage": {
+            "type": "boolean",
+            "description": "Indicates if there is a subsequent page available after the current one.",
+            "example": true
+          },
+          "hasPreviousPage": {
+            "type": "boolean",
+            "description": "Indicates if there is a preceding page available before the current one.",
+            "example": true
+          }
+        },
+        "required": [
+          "totalItems",
+          "remainingItems",
+          "returnedItems",
+          "itemsPerPage",
+          "currentPage",
+          "totalPages",
+          "hasNextPage",
+          "hasPreviousPage"
+        ]
+      },
       "GetManagedOrganizationsOutput": {
         "type": "object",
         "properties": {
@@ -20171,9 +20356,12 @@
             "items": {
               "$ref": "#/components/schemas/ManagedOrganizationOutput"
             }
+          },
+          "pagination": {
+            "$ref": "#/components/schemas/PaginationMetaDto"
           }
         },
-        "required": ["status", "data"]
+        "required": ["status", "data", "pagination"]
       },
       "UpdateOrganizationInput": {
         "type": "object",
@@ -22189,60 +22377,6 @@
         },
         "required": ["status", "data"]
       },
-      "PaginationMetaDto": {
-        "type": "object",
-        "properties": {
-          "totalItems": {
-            "type": "number",
-            "minimum": 0,
-            "description": "The total number of items available across all pages, matching the query criteria.",
-            "example": 123
-          },
-          "remainingItems": {
-            "type": "number",
-            "minimum": 0,
-            "description": "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
-            "example": 103
-          },
-          "itemsPerPage": {
-            "type": "number",
-            "minimum": 1,
-            "description": "The maximum number of items requested per page.",
-            "example": 10
-          },
-          "currentPage": {
-            "type": "number",
-            "minimum": 1,
-            "description": "The current page number being returned.",
-            "example": 2
-          },
-          "totalPages": {
-            "type": "number",
-            "minimum": 0,
-            "description": "The total number of pages available.",
-            "example": 13
-          },
-          "hasNextPage": {
-            "type": "boolean",
-            "description": "Indicates if there is a subsequent page available after the current one.",
-            "example": true
-          },
-          "hasPreviousPage": {
-            "type": "boolean",
-            "description": "Indicates if there is a preceding page available before the current one.",
-            "example": true
-          }
-        },
-        "required": [
-          "totalItems",
-          "remainingItems",
-          "itemsPerPage",
-          "currentPage",
-          "totalPages",
-          "hasNextPage",
-          "hasPreviousPage"
-        ]
-      },
       "GetBookingsOutput_2024_08_13": {
         "type": "object",
         "properties": {
diff --git a/packages/platform/types/api.ts b/packages/platform/types/api.ts
index c50dccd49e469b..daea8e54cfa748 100644
--- a/packages/platform/types/api.ts
+++ b/packages/platform/types/api.ts
@@ -1,6 +1,4 @@
-import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
-import { Transform } from "class-transformer";
-import { IsNumber, Min, Max, IsOptional } from "class-validator";
+import { ApiProperty } from "@nestjs/swagger";
 import { IsEnum } from "class-validator";
 import type { Response as BaseResponse } from "express";
 
@@ -38,41 +36,6 @@ export type ApiResponse<T = undefined> = T extends undefined
 
 export type ApiResponseMaybeRedirect<T = undefined> = ApiResponse<T> | ApiRedirectResponseType;
 
-export class Pagination {
-  @ApiPropertyOptional({ description: "The number of items to return", example: 10 })
-  @Transform(({ value }: { value: string }) => value && parseInt(value))
-  @IsNumber()
-  @Min(1)
-  @Max(250)
-  @IsOptional()
-  limit?: number;
-
-  @ApiPropertyOptional({ description: "The number of items to skip", example: 0 })
-  @Transform(({ value }: { value: string }) => value && parseInt(value))
-  @IsNumber()
-  @Min(0)
-  @Max(250)
-  @IsOptional()
-  offset?: number;
-}
-
-export class SkipTakePagination {
-  @ApiProperty({ required: false, description: "The number of items to return", example: 10 })
-  @Transform(({ value }: { value: string }) => value && parseInt(value))
-  @IsNumber()
-  @Min(1)
-  @Max(250)
-  @IsOptional()
-  take?: number;
-
-  @ApiProperty({ required: false, description: "The number of items to skip", example: 0 })
-  @Transform(({ value }: { value: string }) => value && parseInt(value))
-  @IsNumber()
-  @Min(0)
-  @IsOptional()
-  skip?: number;
-}
-
 export class ApiResponseWithoutData {
   @ApiProperty({ example: SUCCESS_STATUS, enum: [SUCCESS_STATUS, ERROR_STATUS] })
   @IsEnum([SUCCESS_STATUS, ERROR_STATUS])
diff --git a/packages/platform/types/bookings/2024-08-13/outputs/get-bookings.output.ts b/packages/platform/types/bookings/2024-08-13/outputs/get-bookings.output.ts
index dabc39cf332242..3004967afee37f 100644
--- a/packages/platform/types/bookings/2024-08-13/outputs/get-bookings.output.ts
+++ b/packages/platform/types/bookings/2024-08-13/outputs/get-bookings.output.ts
@@ -1,77 +1,16 @@
 import { ApiProperty, ApiExtraModels, getSchemaPath } from "@nestjs/swagger";
 import { Type } from "class-transformer";
-import { IsBoolean, IsEnum, IsInt, Min, ValidateNested } from "class-validator";
+import { IsEnum, ValidateNested } from "class-validator";
 
 import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
 import {
   BookingOutput_2024_08_13,
   GetRecurringSeatedBookingOutput_2024_08_13,
   GetSeatedBookingOutput_2024_08_13,
+  PaginationMetaDto,
   RecurringBookingOutput_2024_08_13,
 } from "@calcom/platform-types";
 
-export class PaginationMetaDto {
-  @ApiProperty({
-    description: "The total number of items available across all pages, matching the query criteria.",
-    example: 123,
-    minimum: 0,
-  })
-  @IsInt()
-  @Min(0)
-  totalItems!: number;
-
-  @ApiProperty({
-    description:
-      "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
-    example: 103, // e.g., if totalItems=123, skip=10, itemsPerPage=10 -> 123 - (10 + 10) = 103
-    minimum: 0,
-  })
-  @IsInt()
-  @Min(0)
-  remainingItems!: number;
-
-  @ApiProperty({
-    description: "The maximum number of items requested per page.",
-    example: 10,
-    minimum: 1,
-  })
-  @IsInt()
-  @Min(1) // Typically, you request at least 1 item per page
-  itemsPerPage!: number;
-
-  @ApiProperty({
-    description: "The current page number being returned.",
-    example: 2, // e.g., if skip=10, itemsPerPage=10 -> page 2
-    minimum: 1,
-  })
-  @IsInt()
-  @Min(1) // Page numbers usually start from 1
-  currentPage!: number;
-
-  @ApiProperty({
-    description: "The total number of pages available.",
-    example: 13, // e.g., if totalItems=123, itemsPerPage=10 -> 13 pages
-    minimum: 0, // Can be 0 if totalItems is 0
-  })
-  @IsInt()
-  @Min(0)
-  totalPages!: number;
-
-  @ApiProperty({
-    description: "Indicates if there is a subsequent page available after the current one.",
-    example: true,
-  })
-  @IsBoolean()
-  hasNextPage!: boolean;
-
-  @ApiProperty({
-    description: "Indicates if there is a preceding page available before the current one.",
-    example: true,
-  })
-  @IsBoolean()
-  hasPreviousPage!: boolean;
-}
-
 @ApiExtraModels(
   BookingOutput_2024_08_13,
   RecurringBookingOutput_2024_08_13,
diff --git a/packages/platform/types/index.ts b/packages/platform/types/index.ts
index 0a4590491a2500..eede061db00a55 100644
--- a/packages/platform/types/index.ts
+++ b/packages/platform/types/index.ts
@@ -13,3 +13,5 @@ export * from "./embed";
 export * from "./oauth-clients";
 export * from "./routing-forms";
 export * from "./me";
+export * from "./pagination/pagination.input";
+export * from "./pagination/pagination.output";
diff --git a/packages/platform/types/pagination/pagination.input.ts b/packages/platform/types/pagination/pagination.input.ts
new file mode 100644
index 00000000000000..be2853e64d6aae
--- /dev/null
+++ b/packages/platform/types/pagination/pagination.input.ts
@@ -0,0 +1,52 @@
+import { ApiPropertyOptional } from "@nestjs/swagger";
+import { Transform } from "class-transformer";
+import { IsNumber, Min, Max, IsOptional } from "class-validator";
+
+export class Pagination {
+  @ApiPropertyOptional({ description: "The number of items to return", example: 10 })
+  @Transform(({ value }: { value: string }) => value && parseInt(value))
+  @IsNumber()
+  @Min(1)
+  @Max(250)
+  @IsOptional()
+  limit?: number;
+
+  @ApiPropertyOptional({ description: "The number of items to skip", example: 0 })
+  @Transform(({ value }: { value: string }) => value && parseInt(value))
+  @IsNumber()
+  @Min(0)
+  @Max(250)
+  @IsOptional()
+  offset?: number;
+}
+
+const DEFAULT_TAKE = 250;
+const DEFAULT_SKIP = 0;
+
+export class SkipTakePagination {
+  @ApiPropertyOptional({
+    description: "Maximum number of items to return",
+    example: 25,
+    default: DEFAULT_TAKE,
+    minimum: 1,
+    maximum: DEFAULT_TAKE,
+  })
+  @Transform(({ value }: { value: string }) => (value ? parseInt(value) : DEFAULT_TAKE))
+  @IsNumber()
+  @Min(1)
+  @Max(DEFAULT_TAKE)
+  @IsOptional()
+  take: number = DEFAULT_TAKE;
+
+  @ApiPropertyOptional({
+    description: "Number of items to skip",
+    example: 0,
+    default: DEFAULT_SKIP,
+    minimum: 0,
+  })
+  @Transform(({ value }: { value: string }) => (value ? parseInt(value) : DEFAULT_SKIP))
+  @IsNumber()
+  @Min(0)
+  @IsOptional()
+  skip: number = DEFAULT_SKIP;
+}
diff --git a/packages/platform/types/pagination/pagination.output.ts b/packages/platform/types/pagination/pagination.output.ts
new file mode 100644
index 00000000000000..dfa9832601b72c
--- /dev/null
+++ b/packages/platform/types/pagination/pagination.output.ts
@@ -0,0 +1,72 @@
+import { ApiProperty } from "@nestjs/swagger";
+import { IsBoolean, IsInt, Min } from "class-validator";
+
+export class PaginationMetaDto {
+  @ApiProperty({
+    description: "The total number of items available across all pages, matching the query criteria.",
+    example: 123,
+    minimum: 0,
+  })
+  @IsInt()
+  @Min(0)
+  totalItems!: number;
+
+  @ApiProperty({
+    description:
+      "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
+    example: 103, // e.g., if totalItems=123, skip=10, itemsPerPage=10 -> 123 - (10 + 10) = 103
+    minimum: 0,
+  })
+  @IsInt()
+  @Min(0)
+  remainingItems!: number;
+
+  @ApiProperty({
+    description: "The number of items returned in the current page.",
+    example: 10,
+  })
+  @IsInt()
+  @Min(0)
+  returnedItems!: number;
+
+  @ApiProperty({
+    description: "The maximum number of items requested per page.",
+    example: 10,
+    minimum: 1,
+  })
+  @IsInt()
+  @Min(1) // Typically, you request at least 1 item per page
+  itemsPerPage!: number;
+
+  @ApiProperty({
+    description: "The current page number being returned.",
+    example: 2, // e.g., if skip=10, itemsPerPage=10 -> page 2
+    minimum: 1,
+  })
+  @IsInt()
+  @Min(1) // Page numbers usually start from 1
+  currentPage!: number;
+
+  @ApiProperty({
+    description: "The total number of pages available.",
+    example: 13, // e.g., if totalItems=123, itemsPerPage=10 -> 13 pages
+    minimum: 0, // Can be 0 if totalItems is 0
+  })
+  @IsInt()
+  @Min(0)
+  totalPages!: number;
+
+  @ApiProperty({
+    description: "Indicates if there is a subsequent page available after the current one.",
+    example: true,
+  })
+  @IsBoolean()
+  hasNextPage!: boolean;
+
+  @ApiProperty({
+    description: "Indicates if there is a preceding page available before the current one.",
+    example: true,
+  })
+  @IsBoolean()
+  hasPreviousPage!: boolean;
+}


Reviews:
user: login: cubic-dev-ai[bot]
body: cubic found 2 issues across 14 files. Review them in [cubic.dev](https://cubic.dev/pr/calcom/cal.com/pull/21359)
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T10:05:22Z
user: login: supalarry
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T09:45:15Z
user: login: supalarry
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T09:48:03Z
user: login: ThyMinimalDev
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-27T10:50:30Z

Review comments:
diff_hunk: @@ -34,11 +35,26 @@ export class ManagedOrganizationsRepository {
     });
   }
 
-  async getByManagerOrganizationId(managerOrganizationId: number) {
-    return this.dbRead.prisma.managedOrganization.findMany({
-      where: {
-        managerOrganizationId,
-      },
-    });
+  async getByManagerOrganizationIdPaginated(managerOrganizationId: number, pagination: SkipTakePagination) {
+    const { skip, take } = pagination;
+
+    const where: Prisma.ManagedOrganizationWhereInput = {
+      managerOrganizationId,
+    };
+
+    const [totalItems, linkRows] = await this.dbRead.prisma.$transaction([
+      this.dbRead.prisma.managedOrganization.count({ where }),
+      this.dbRead.prisma.managedOrganization.findMany({
+        where,
+        skip,
+        take,
+        orderBy: { managedOrganizationId: "asc" },
+        include: { managedOrganization: true },
path: apps/api/v2/src/modules/organizations/organizations/managed-organizations.repository.ts
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":8,"steps":[{"text":"","toolCalls":[{"args":{"command":"grep -R \"managedOrganizationId: \\\"asc\\\"\" -n"},"toolName":"executeCommand"}]}]} -->
Using `include` retrieves all columns of the related `managedOrganization` table, pulling unnecessary data and potentially exposing sensitive fields. Project guidelines explicitly require using `select` to fetch only needed fields for performance and security reasons.
created_at: 2025-05-20T10:05:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,72 @@
+import { ApiProperty } from "@nestjs/swagger";
+import { IsBoolean, IsInt, Min } from "class-validator";
+
+export class PaginationMetaDto {
+  @ApiProperty({
+    description: "The total number of items available across all pages, matching the query criteria.",
+    example: 123,
+    minimum: 0,
+  })
+  @IsInt()
+  @Min(0)
+  totalItems!: number;
+
+  @ApiProperty({
+    description:
+      "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
path: packages/platform/types/pagination/pagination.output.ts
user: login: cubic-dev-ai[bot]
body: <!-- metadata:{"confidence":6,"steps":[{"text":"","toolCalls":[{"args":{"pattern":"**/pagination.output.ts"},"toolName":"listFiles"}]},{"text":"","toolCalls":[{"args":{"command":"sed -n '1,160p' packages/platform/types/pagination/pagination.output.ts"},"toolName":"executeCommand"}]}]} -->
Description suggests subtracting itemsPerPage instead of the actual number of items returned, which would yield negative remainingItems on the last page (e.g., 123 - (120 + 10) = -7). This mismatched formula can confuse users and contradicts the @Min(0) constraint.
created_at: 2025-05-20T10:05:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,11 +35,26 @@ export class ManagedOrganizationsRepository {
     });
   }
 
-  async getByManagerOrganizationId(managerOrganizationId: number) {
-    return this.dbRead.prisma.managedOrganization.findMany({
-      where: {
-        managerOrganizationId,
-      },
-    });
+  async getByManagerOrganizationIdPaginated(managerOrganizationId: number, pagination: SkipTakePagination) {
+    const { skip, take } = pagination;
+
+    const where: Prisma.ManagedOrganizationWhereInput = {
+      managerOrganizationId,
+    };
+
+    const [totalItems, linkRows] = await this.dbRead.prisma.$transaction([
+      this.dbRead.prisma.managedOrganization.count({ where }),
+      this.dbRead.prisma.managedOrganization.findMany({
+        where,
+        skip,
+        take,
+        orderBy: { managedOrganizationId: "asc" },
+        include: { managedOrganization: true },
path: apps/api/v2/src/modules/organizations/organizations/managed-organizations.repository.ts
user: login: supalarry
body: I know include is not performant, but in this case the only alternative is to not include which would return ids of managed organizations and then have a separate call to fetch all organizations (teams model) by the ids, which would result in an additional database call.
created_at: 2025-05-27T09:45:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,72 @@
+import { ApiProperty } from "@nestjs/swagger";
+import { IsBoolean, IsInt, Min } from "class-validator";
+
+export class PaginationMetaDto {
+  @ApiProperty({
+    description: "The total number of items available across all pages, matching the query criteria.",
+    example: 123,
+    minimum: 0,
+  })
+  @IsInt()
+  @Min(0)
+  totalItems!: number;
+
+  @ApiProperty({
+    description:
+      "The number of items remaining to be fetched *after* the current page. Calculated as: `totalItems - (skip + itemsPerPage)`.",
path: packages/platform/types/pagination/pagination.output.ts
user: login: supalarry
body: It will not be -7 and will always be at lesat 0 because in `apps/api/v2/src/lib/pagination/pagination.ts` `getRemainingItems` function it is clamped to minimum of 0.
created_at: 2025-05-27T09:48:03Z
author_association: CONTRIBUTOR

PR comments:
user: login: linear[bot]
created_at: 2025-05-16T14:24:12Z
body: <p><a href="https://linear.app/calcom/issue/CAL-5293/feat-v2-managed-organizations-pagination">CAL-5293 feat: v2 managed organizations pagination</a></p>
author_association: NONE
user: login: vercel[bot]
created_at: 2025-05-16T14:24:17Z
body: [vc]: #zDnsB3AY/0xeuuPTLfU0iJvNQJn6tHco3wUqhyPv9Mg=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJjYWwiLCJyb290RGlyZWN0b3J5IjoiYXBwcy93ZWIiLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiIn0sImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9jYWwvY2FsLzh4NlQ5aXdrR0pycDdkV0UycGpxaTJnSjFRUjQiLCJuZXh0Q29tbWl0U3RhdHVzIjoiSUdOT1JFRCIsInByZXZpZXdVcmwiOiJjYWwtZ2l0LWxhdXJpcy1jYWwtNTI5My1mZWF0LXYyLW1hbmFnZWQtb3JnYW5pemF0aW9uLWFmMmEzYS1jYWwudmVyY2VsLmFwcCJ9XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)


<details><summary>1 Skipped Deployment</summary>

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **cal** | ⬜️ Ignored ([Inspect](https://vercel.com/cal/cal/8x6T9iwkGJrp7dWE2pjqi2gJ1QR4)) | [Visit Preview](https://cal-git-lauris-cal-5293-feat-v2-managed-organization-af2a3a-cal.vercel.app) |  | May 27, 2025 8:36am |
</details>


author_association: NONE
user: login: graphite-app[bot]
created_at: 2025-05-20T10:00:12Z
body: ### Graphite Automations
<details><summary><a href="https://app.graphite.dev/automations/?org=calcom&ruleId=qoTwHtX8MnP39HKxIt4V&ref=gt-automation-github-comment">"Add consumer team as reviewer"</a> took an action on this PR • (05/20/25)</summary><p>1 reviewer was added to this PR based on Keith Williams's automation.</p></details>
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-05-20T10:26:25Z
body: <!-- GENERATED-E2E-RESULTS -->
## E2E results are ready!
- [Workflow #61709.2 latest results](https://calcom.github.io/test-results/reports/lauris/cal-5293-feat-v2-managed-organizations-pagination/15270552830/2)
author_association: CONTRIBUTOR