diff --git a/apps/api/v2/src/modules/organizations/delegation-credentials/organizations-delegation-credential.module.ts b/apps/api/v2/src/modules/organizations/delegation-credentials/organizations-delegation-credential.module.ts index bc382e97ea..7b5ecbad9f 100644 --- a/apps/api/v2/src/modules/organizations/delegation-credentials/organizations-delegation-credential.module.ts +++ b/apps/api/v2/src/modules/organizations/delegation-credentials/organizations-delegation-credential.module.ts @@ -1,5 +1,9 @@ +import { BullModule } from "@nestjs/bull"; +import { Module } from "@nestjs/common"; +import { OrganizationsDelegationCredentialService } from "./services/organizations-delegation-credential.service"; import { CalendarsModule } from "@/ee/calendars/calendars.module"; import { CALENDARS_QUEUE, CalendarsProcessor } from "@/ee/calendars/processors/calendars.processor"; +import { CalendarsTaskerModule } from "@/lib/modules/calendars-tasker.module"; import { MembershipsModule } from "@/modules/memberships/memberships.module"; import { OrganizationsDelegationCredentialController } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.controller"; import { OrganizationsDelegationCredentialRepository } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.repository"; @@ -7,10 +11,6 @@ import { OrganizationsRepository } from "@/modules/organizations/index/organizat import { PrismaModule } from "@/modules/prisma/prisma.module"; import { RedisModule } from "@/modules/redis/redis.module"; import { StripeModule } from "@/modules/stripe/stripe.module"; -import { BullModule } from "@nestjs/bull"; -import { Module } from "@nestjs/common"; - -import { OrganizationsDelegationCredentialService } from "./services/organizations-delegation-credential.service"; @Module({ imports: [ @@ -26,6 +26,7 @@ import { OrganizationsDelegationCredentialService } from "./services/organizatio duration: 1000, }, }), + CalendarsTaskerModule, ], providers: [ OrganizationsDelegationCredentialService, @@ -34,6 +35,10 @@ import { OrganizationsDelegationCredentialService } from "./services/organizatio CalendarsProcessor, ], controllers: [OrganizationsDelegationCredentialController], - exports: [OrganizationsDelegationCredentialRepository, OrganizationsDelegationCredentialService, BullModule], + exports: [ + OrganizationsDelegationCredentialRepository, + OrganizationsDelegationCredentialService, + BullModule, + ], }) export class OrganizationsDelegationCredentialModule {} diff --git a/apps/api/v2/src/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service.spec.ts b/apps/api/v2/src/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service.spec.ts index 3c23938d68..33c636dff7 100644 --- a/apps/api/v2/src/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service.spec.ts +++ b/apps/api/v2/src/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service.spec.ts @@ -2,9 +2,11 @@ import { CALENDARS_QUEUE, DEFAULT_CALENDARS_JOB, } from "@/ee/calendars/processors/calendars.processor"; +import { CalendarsTasker } from "@/lib/services/tasker/calendars-tasker.service"; import { OrganizationsDelegationCredentialRepository } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.repository"; import { OrganizationsDelegationCredentialService } from "@/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service"; import { Logger } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; import { getQueueToken } from "@nestjs/bull"; import { Test, TestingModule } from "@nestjs/testing"; @@ -12,6 +14,8 @@ describe("OrganizationsDelegationCredentialService", () => { let service: OrganizationsDelegationCredentialService; let mockRepository: OrganizationsDelegationCredentialRepository; let mockQueue: { getJob: jest.Mock; add: jest.Mock }; + let mockCalendarsTasker: { dispatch: jest.Mock }; + let mockConfigService: { get: jest.Mock }; const orgId = 1; const domain = "example.com"; @@ -22,6 +26,14 @@ describe("OrganizationsDelegationCredentialService", () => { add: jest.fn().mockResolvedValue(undefined), }; + mockCalendarsTasker = { + dispatch: jest.fn().mockResolvedValue({ runId: "test-run-id" }), + }; + + mockConfigService = { + get: jest.fn().mockReturnValue(false), + }; + const module: TestingModule = await Test.createTestingModule({ providers: [ OrganizationsDelegationCredentialService, @@ -35,6 +47,14 @@ describe("OrganizationsDelegationCredentialService", () => { provide: getQueueToken(CALENDARS_QUEUE), useValue: mockQueue, }, + { + provide: CalendarsTasker, + useValue: mockCalendarsTasker, + }, + { + provide: ConfigService, + useValue: mockConfigService, + }, ], }).compile(); @@ -215,5 +235,54 @@ describe("OrganizationsDelegationCredentialService", () => { await expect(service.ensureDefaultCalendarsForUser(orgId, userId, userEmail)).resolves.toBeUndefined(); }); + + describe("when enableAsyncTasker is true", () => { + beforeEach(() => { + mockConfigService.get.mockReturnValue(true); + }); + + it("uses CalendarsTasker.dispatch instead of Bull queue", async () => { + (mockRepository.findEnabledByOrgIdAndDomain as jest.Mock).mockResolvedValue({ + id: "cred-1", + }); + + await service.ensureDefaultCalendarsForUser(orgId, userId, userEmail); + + expect(mockConfigService.get).toHaveBeenCalledWith("enableAsyncTasker"); + expect(mockCalendarsTasker.dispatch).toHaveBeenCalledWith( + "ensureDefaultCalendars", + { userId }, + { idempotencyKey: `${DEFAULT_CALENDARS_JOB}_${userId}`, idempotencyKeyTTL: "1h" } + ); + expect(mockQueue.add).not.toHaveBeenCalled(); + expect(mockQueue.getJob).not.toHaveBeenCalled(); + }); + + it("does not call CalendarsTasker when no delegation credential exists", async () => { + (mockRepository.findEnabledByOrgIdAndDomain as jest.Mock).mockResolvedValue(null); + + await service.ensureDefaultCalendarsForUser(orgId, userId, userEmail); + + expect(mockCalendarsTasker.dispatch).not.toHaveBeenCalled(); + expect(mockQueue.add).not.toHaveBeenCalled(); + }); + + it("does not throw when CalendarsTasker.dispatch fails", async () => { + (mockRepository.findEnabledByOrgIdAndDomain as jest.Mock).mockResolvedValue({ + id: "cred-1", + }); + mockCalendarsTasker.dispatch.mockRejectedValue(new Error("Tasker error")); + + await expect(service.ensureDefaultCalendarsForUser(orgId, userId, userEmail)).resolves.toBeUndefined(); + }); + + it("returns early for invalid email without calling tasker", async () => { + await service.ensureDefaultCalendarsForUser(orgId, userId, "invalidemail"); + + expect(Logger.prototype.warn).toHaveBeenCalledWith(`Invalid email format for user ${userId}: missing domain`); + expect(mockCalendarsTasker.dispatch).not.toHaveBeenCalled(); + expect(mockRepository.findEnabledByOrgIdAndDomain).not.toHaveBeenCalled(); + }); + }); }); }); diff --git a/apps/api/v2/src/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service.ts b/apps/api/v2/src/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service.ts index de4e065211..40ece00996 100644 --- a/apps/api/v2/src/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service.ts +++ b/apps/api/v2/src/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service.ts @@ -1,8 +1,21 @@ +import { encryptServiceAccountKey } from "@calcom/platform-libraries"; +import { + addDelegationCredential, + type TServiceAccountKeySchema, + toggleDelegationCredentialEnabled, +} from "@calcom/platform-libraries/app-store"; +import type { DelegationCredential, Prisma, User } from "@calcom/prisma/client"; +import { InjectQueue } from "@nestjs/bull"; +import { Injectable, Logger, NotFoundException } from "@nestjs/common"; +import { ConfigService } from "@nestjs/config"; +import { Queue } from "bull"; +import { AppConfig } from "@/config/type"; import { CALENDARS_QUEUE, DEFAULT_CALENDARS_JOB, DefaultCalendarsJobDataType, } from "@/ee/calendars/processors/calendars.processor"; +import { CalendarsTasker } from "@/lib/services/tasker/calendars-tasker.service"; import { CreateDelegationCredentialInput } from "@/modules/organizations/delegation-credentials/inputs/create-delegation-credential.input"; import { GoogleServiceAccountKeyInput, @@ -10,17 +23,30 @@ import { } from "@/modules/organizations/delegation-credentials/inputs/service-account-key.input"; import { UpdateDelegationCredentialInput } from "@/modules/organizations/delegation-credentials/inputs/update-delegation-credential.input"; import { OrganizationsDelegationCredentialRepository } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.repository"; -import { InjectQueue } from "@nestjs/bull"; -import { Injectable, NotFoundException, Logger } from "@nestjs/common"; -import { Queue } from "bull"; -import { encryptServiceAccountKey } from "@calcom/platform-libraries"; -import { - addDelegationCredential, - toggleDelegationCredentialEnabled, - type TServiceAccountKeySchema, -} from "@calcom/platform-libraries/app-store"; -import type { User } from "@calcom/prisma/client"; +type DelegationCredentialWithWorkspacePlatform = { + workspacePlatform: { + name: string; + id: number; + enabled: boolean; + createdAt: Date; + updatedAt: Date; + slug: string; + description: string; + defaultServiceAccountKey: Prisma.JsonValue; + }; +} & { + id: string; + organizationId: number; + serviceAccountKey: Prisma.JsonValue; + enabled: boolean; + lastEnabledAt: Date | null; + lastDisabledAt: Date | null; + domain: string; + createdAt: Date; + updatedAt: Date; + workspacePlatformId: number; +}; @Injectable() export class OrganizationsDelegationCredentialService { @@ -28,13 +54,15 @@ export class OrganizationsDelegationCredentialService { constructor( private readonly organizationsDelegationCredentialRepository: OrganizationsDelegationCredentialRepository, + private readonly calendarsTasker: CalendarsTasker, + private readonly configService: ConfigService, @InjectQueue(CALENDARS_QUEUE) private readonly calendarsQueue: Queue ) {} async createDelegationCredential( orgId: number, delegatedServiceAccountUser: User, body: CreateDelegationCredentialInput - ) { + ): Promise> | null | undefined> { const delegationCredential = await addDelegationCredential({ input: body, ctx: { user: { id: delegatedServiceAccountUser.id, organizationId: orgId } }, @@ -47,7 +75,7 @@ export class OrganizationsDelegationCredentialService { delegationCredentialId: string, delegatedServiceAccountUser: User, body: UpdateDelegationCredentialInput - ) { + ): Promise { let delegationCredential = await this.organizationsDelegationCredentialRepository.findByIdWithWorkspacePlatform( delegationCredentialId @@ -82,7 +110,7 @@ export class OrganizationsDelegationCredentialService { return { ...delegationCredential, enabled: body?.enabled ?? delegationCredential.enabled }; } - async ensureDefaultCalendars(orgId: number, domain: string) { + async ensureDefaultCalendars(orgId: number, domain: string): Promise { try { const delegatedUserProfiles = await this.organizationsDelegationCredentialRepository.findDelegatedUserProfiles(orgId, domain); @@ -123,7 +151,7 @@ export class OrganizationsDelegationCredentialService { } } - async ensureDefaultCalendarsForUser(orgId: number, userId: number, userEmail: string) { + async ensureDefaultCalendarsForUser(orgId: number, userId: number, userEmail: string): Promise { try { const emailParts = userEmail.split("@"); if (emailParts.length < 2 || !emailParts[1]) { @@ -133,23 +161,37 @@ export class OrganizationsDelegationCredentialService { const emailDomain = `@${emailParts[1]}`; const delegationCredential = - await this.organizationsDelegationCredentialRepository.findEnabledByOrgIdAndDomain(orgId, emailDomain); + await this.organizationsDelegationCredentialRepository.findEnabledByOrgIdAndDomain( + orgId, + emailDomain + ); if (!delegationCredential) { return; } + if (this.configService.get("enableAsyncTasker")) { + this.logger.log(`Adding default calendar job for user with id: ${userId}`); + await this.calendarsTasker.dispatch( + "ensureDefaultCalendars", + { + userId, + }, + { idempotencyKey: `${DEFAULT_CALENDARS_JOB}_${userId}`, idempotencyKeyTTL: "1h" } + ); + return; + } + const existingJob = await this.calendarsQueue.getJob(`${DEFAULT_CALENDARS_JOB}_${userId}`); if (existingJob) { await existingJob.remove(); this.logger.log(`Removed existing default calendar job for user with id: ${userId}`); } this.logger.log(`Adding default calendar job for user with id: ${userId}`); - await this.calendarsQueue.add( - DEFAULT_CALENDARS_JOB, - { userId } satisfies DefaultCalendarsJobDataType, - { jobId: `${DEFAULT_CALENDARS_JOB}_${userId}`, removeOnComplete: true } - ); + await this.calendarsQueue.add(DEFAULT_CALENDARS_JOB, { userId } satisfies DefaultCalendarsJobDataType, { + jobId: `${DEFAULT_CALENDARS_JOB}_${userId}`, + removeOnComplete: true, + }); } catch (err) { this.logger.error( err, @@ -163,7 +205,7 @@ export class OrganizationsDelegationCredentialService { delegationCredentialId: string, delegatedServiceAccountUser: User, enabled: boolean - ) { + ): Promise> | null | undefined> { const handlerUser = { id: delegatedServiceAccountUser.id, email: delegatedServiceAccountUser.email, @@ -177,7 +219,7 @@ export class OrganizationsDelegationCredentialService { async updateDelegationCredentialServiceAccountKey( delegationCredentialId: string, serviceAccountKey: GoogleServiceAccountKeyInput | MicrosoftServiceAccountKeyInput - ) { + ): Promise { // First encrypt the service account key const encryptedServiceAccountKey = encryptServiceAccountKey( serviceAccountKey as TServiceAccountKeySchema diff --git a/apps/api/v2/src/modules/organizations/memberships/organizations-membership.controller.e2e-spec.ts b/apps/api/v2/src/modules/organizations/memberships/organizations-membership.controller.e2e-spec.ts index 5f3e4dfebd..838764d186 100644 --- a/apps/api/v2/src/modules/organizations/memberships/organizations-membership.controller.e2e-spec.ts +++ b/apps/api/v2/src/modules/organizations/memberships/organizations-membership.controller.e2e-spec.ts @@ -20,6 +20,7 @@ import { GetAllOrgMemberships } from "@/modules/organizations/memberships/output import { GetOrgMembership } from "@/modules/organizations/memberships/outputs/get-membership.output"; import { OrgUserAttribute } from "@/modules/organizations/memberships/outputs/organization-membership.output"; import { UpdateOrgMembership } from "@/modules/organizations/memberships/outputs/update-membership.output"; +import { OrganizationsDelegationCredentialService } from "@/modules/organizations/delegation-credentials/services/organizations-delegation-credential.service"; import { PrismaModule } from "@/modules/prisma/prisma.module"; import { TeamMembershipOutput } from "@/modules/teams/memberships/outputs/team-membership.output"; import { TokensModule } from "@/modules/tokens/tokens.module"; @@ -146,7 +147,7 @@ describe("Organizations Memberships Endpoints", () => { await app.init(); }); - async function setupAttributes() { + async function setupAttributes(): Promise { textAttribute = await attributesRepositoryFixture.create({ team: { connect: { id: org.id } }, type: "TEXT", @@ -261,7 +262,7 @@ describe("Organizations Memberships Endpoints", () => { }); }); - function userHasCorrectAttributes(attributes: OrgUserAttribute[]) { + function userHasCorrectAttributes(attributes: OrgUserAttribute[]): void { expect(attributes.length).toEqual(4); const responseNumberAttribute = attributes.find((attr) => attr.type === "number"); const responseSingleSelectAttribute = attributes.find((attr) => attr.type === "singleSelect"); @@ -387,6 +388,39 @@ describe("Organizations Memberships Endpoints", () => { }); }); + it("should call ensureDefaultCalendarsForUser when creating membership", async () => { + const newUserEmail = `organizations-memberships-calendars-${randomString()}@api.com`; + const newUser = await userRepositoryFixture.create({ + email: newUserEmail, + username: newUserEmail, + bio, + metadata, + }); + + const ensureDefaultCalendarsSpy = jest + .spyOn(OrganizationsDelegationCredentialService.prototype, "ensureDefaultCalendarsForUser") + .mockResolvedValue(undefined); + + try { + await request(app.getHttpServer()) + .post(`/v2/organizations/${org.id}/memberships`) + .send({ + userId: newUser.id, + accepted: true, + role: "MEMBER", + } satisfies CreateOrgMembershipDto) + .expect(201); + + expect(ensureDefaultCalendarsSpy).toHaveBeenCalledWith(org.id, newUser.id, newUserEmail); + } finally { + ensureDefaultCalendarsSpy.mockRestore(); + await membershipRepositoryFixture.delete( + (await membershipRepositoryFixture.getUserMembershipByTeamId(newUser.id, org.id))?.id ?? 0 + ); + await userRepositoryFixture.deleteByEmail(newUserEmail); + } + }); + it("should update the membership of the org", async () => { return request(app.getHttpServer()) .patch(`/v2/organizations/${org.id}/memberships/${membershipCreatedViaApi.id}`) diff --git a/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.module.ts b/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.module.ts index 4fd946b560..0f7224f480 100644 --- a/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.module.ts +++ b/apps/api/v2/src/modules/organizations/organizations/organizations-organizations.module.ts @@ -1,6 +1,7 @@ import { BullModule } from "@nestjs/bull"; import { Module } from "@nestjs/common"; import { CALENDARS_QUEUE } from "@/ee/calendars/processors/calendars.processor"; +import { CalendarsTaskerModule } from "@/lib/modules/calendars-tasker.module"; import { ApiKeysModule } from "@/modules/api-keys/api-keys.module"; import { ManagedOrganizationsBillingService } from "@/modules/billing/services/managed-organizations.billing.service"; import { MembershipsModule } from "@/modules/memberships/memberships.module"; @@ -35,6 +36,7 @@ import { UsersRepository } from "@/modules/users/users.repository"; duration: 1000, }, }), + CalendarsTaskerModule, ], providers: [ ManagedOrganizationsService, diff --git a/apps/api/v2/src/modules/selected-calendars/selected-calendars.module.ts b/apps/api/v2/src/modules/selected-calendars/selected-calendars.module.ts index 70c226ee8f..86451a6496 100644 --- a/apps/api/v2/src/modules/selected-calendars/selected-calendars.module.ts +++ b/apps/api/v2/src/modules/selected-calendars/selected-calendars.module.ts @@ -4,6 +4,7 @@ import { CalendarsRepository } from "@/ee/calendars/calendars.repository"; import { CALENDARS_QUEUE } from "@/ee/calendars/processors/calendars.processor"; import { CalendarsService } from "@/ee/calendars/services/calendars.service"; import { CalendarsCacheService } from "@/ee/calendars/services/calendars-cache.service"; +import { CalendarsTaskerModule } from "@/lib/modules/calendars-tasker.module"; import { AppsRepository } from "@/modules/apps/apps.repository"; import { CredentialsRepository } from "@/modules/credentials/credentials.repository"; import { OrganizationsDelegationCredentialRepository } from "@/modules/organizations/delegation-credentials/organizations-delegation-credential.repository"; @@ -29,6 +30,7 @@ import { UsersRepository } from "@/modules/users/users.repository"; duration: 1000, }, }), + CalendarsTaskerModule, ], providers: [ SelectedCalendarsRepository, diff --git a/apps/api/v2/tsconfig.json b/apps/api/v2/tsconfig.json index 599bae60ec..bd20b41a4b 100644 --- a/apps/api/v2/tsconfig.json +++ b/apps/api/v2/tsconfig.json @@ -32,7 +32,8 @@ "@calcom/platform-libraries/bookings": ["../../../packages/platform/libraries/bookings.ts"], "@calcom/platform-libraries/private-links": ["../../../packages/platform/libraries/private-links.ts"], "@calcom/platform-libraries/organizations": ["../../../packages/platform/libraries/organizations.ts"], - "@calcom/platform-libraries/errors": ["../../../packages/platform/libraries/errors.ts"] + "@calcom/platform-libraries/errors": ["../../../packages/platform/libraries/errors.ts"], + "@calcom/platform-libraries/calendars": ["../../../packages/platform/libraries/calendars.ts"] }, "incremental": true, "skipLibCheck": true, diff --git a/biome.json b/biome.json index eac2183ec6..07fd71d256 100644 --- a/biome.json +++ b/biome.json @@ -212,7 +212,7 @@ } }, { - "includes": ["**/*.test.ts", "**/*.test.tsx", "**/*.e2e-spec.ts", "**/*.integration-test.ts"], + "includes": ["**/*.test.ts", "**/*.test.tsx", "**/*.spec.ts", "**/*.e2e-spec.ts", "**/*.integration-test.ts"], "linter": { "rules": { "complexity": { diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json index cae5032d91..8c3870e063 100644 --- a/docs/api-reference/v2/openapi.json +++ b/docs/api-reference/v2/openapi.json @@ -28,11 +28,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -41,10 +41,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -541,8 +541,8 @@ "required": false, "in": "query", "description": "Filter by assigned attribute option ids. ids must be separated by a comma.", + "example": "?assignedOptionIds=aaaaaaaa-bbbb-cccc-dddd-eeeeee1eee,aaaaaaaa-bbbb-cccc-dddd-eeeeee2eee", "schema": { - "example": "?assignedOptionIds=aaaaaaaa-bbbb-cccc-dddd-eeeeee1eee,aaaaaaaa-bbbb-cccc-dddd-eeeeee2eee", "type": "array", "items": { "type": "string" @@ -554,8 +554,8 @@ "required": false, "in": "query", "description": "Filter by teamIds. Team ids must be separated by a comma.", + "example": "?teamIds=100,200", "schema": { - "example": "?teamIds=100,200", "type": "array", "items": { "type": "number" @@ -633,8 +633,8 @@ "required": false, "in": "query", "description": "Filter by assigned attribute option ids. ids must be separated by a comma.", + "example": "?assignedOptionIds=aaaaaaaa-bbbb-cccc-dddd-eeeeee1eee,aaaaaaaa-bbbb-cccc-dddd-eeeeee2eee", "schema": { - "example": "?assignedOptionIds=aaaaaaaa-bbbb-cccc-dddd-eeeeee1eee,aaaaaaaa-bbbb-cccc-dddd-eeeeee2eee", "type": "array", "items": { "type": "string" @@ -646,8 +646,8 @@ "required": false, "in": "query", "description": "Filter by teamIds. Team ids must be separated by a comma.", + "example": "?teamIds=100,200", "schema": { - "example": "?teamIds=100,200", "type": "array", "items": { "type": "number" @@ -869,8 +869,8 @@ "required": false, "in": "query", "description": "Filter bookings by status. If you want to filter by multiple statuses, separate them with a comma.", + "example": "?status=upcoming,past", "schema": { - "example": "?status=upcoming,past", "type": "array", "items": { "type": "string", @@ -889,8 +889,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's email address.", + "example": "example@domain.com", "schema": { - "example": "example@domain.com", "type": "string" } }, @@ -899,8 +899,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's name.", + "example": "John Doe", "schema": { - "example": "John Doe", "type": "string" } }, @@ -909,8 +909,8 @@ "required": false, "in": "query", "description": "Filter bookings by the booking Uid.", + "example": "2NtaeaVcKfpmSZ4CthFdfk", "schema": { - "example": "2NtaeaVcKfpmSZ4CthFdfk", "type": "string" } }, @@ -919,8 +919,8 @@ "required": false, "in": "query", "description": "Filter bookings by event type ids belonging to the user. Event type ids must be separated by a comma.", + "example": "?eventTypeIds=100,200", "schema": { - "example": "?eventTypeIds=100,200", "type": "string" } }, @@ -929,8 +929,8 @@ "required": false, "in": "query", "description": "Filter bookings by event type id belonging to the user.", + "example": "?eventTypeId=100", "schema": { - "example": "?eventTypeId=100", "type": "string" } }, @@ -939,8 +939,8 @@ "required": false, "in": "query", "description": "Filter bookings by team ids that user is part of. Team ids must be separated by a comma.", + "example": "?teamIds=50,60", "schema": { - "example": "?teamIds=50,60", "type": "string" } }, @@ -949,8 +949,8 @@ "required": false, "in": "query", "description": "Filter bookings by team id that user is part of", + "example": "?teamId=50", "schema": { - "example": "?teamId=50", "type": "string" } }, @@ -959,8 +959,8 @@ "required": false, "in": "query", "description": "Filter bookings with start after this date string.", + "example": "?afterStart=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterStart=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -969,8 +969,8 @@ "required": false, "in": "query", "description": "Filter bookings with end before this date string.", + "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "schema": { - "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "type": "string" } }, @@ -979,8 +979,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been created after this date string.", + "example": "?afterCreatedAt=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterCreatedAt=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -989,8 +989,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been created before this date string.", + "example": "?beforeCreatedAt=2025-03-14T11:00:00.000Z", "schema": { - "example": "?beforeCreatedAt=2025-03-14T11:00:00.000Z", "type": "string" } }, @@ -999,8 +999,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been updated after this date string.", + "example": "?afterUpdatedAt=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterUpdatedAt=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -1009,8 +1009,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been updated before this date string.", + "example": "?beforeUpdatedAt=2025-03-14T11:00:00.000Z", "schema": { - "example": "?beforeUpdatedAt=2025-03-14T11:00:00.000Z", "type": "string" } }, @@ -1019,8 +1019,8 @@ "required": false, "in": "query", "description": "Sort results by their start time in ascending or descending order.", + "example": "?sortStart=asc OR ?sortStart=desc", "schema": { - "example": "?sortStart=asc OR ?sortStart=desc", "enum": [ "asc", "desc" @@ -1033,8 +1033,8 @@ "required": false, "in": "query", "description": "Sort results by their end time in ascending or descending order.", + "example": "?sortEnd=asc OR ?sortEnd=desc", "schema": { - "example": "?sortEnd=asc OR ?sortEnd=desc", "enum": [ "asc", "desc" @@ -1047,8 +1047,8 @@ "required": false, "in": "query", "description": "Sort results by their creation time (when booking was made) in ascending or descending order.", + "example": "?sortCreated=asc OR ?sortCreated=desc", "schema": { - "example": "?sortCreated=asc OR ?sortCreated=desc", "enum": [ "asc", "desc" @@ -1061,8 +1061,8 @@ "required": false, "in": "query", "description": "Sort results by their updated time (for example when booking status changes) in ascending or descending order.", + "example": "?sortUpdated=asc OR ?sortUpdated=desc", "schema": { - "example": "?sortUpdated=asc OR ?sortUpdated=desc", "enum": [ "asc", "desc" @@ -1075,9 +1075,9 @@ "required": false, "in": "query", "description": "The number of items to return", + "example": 10, "schema": { "default": 100, - "example": 10, "type": "number" } }, @@ -1086,9 +1086,9 @@ "required": false, "in": "query", "description": "The number of items to skip", + "example": 0, "schema": { "default": 0, - "example": 0, "type": "number" } }, @@ -1097,8 +1097,8 @@ "required": false, "in": "query", "description": "Filter bookings by ids of users within your organization.", + "example": "?userIds=100,200", "schema": { - "example": "?userIds=100,200", "type": "string" } }, @@ -1317,11 +1317,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -1330,10 +1330,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -1736,11 +1736,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -1749,10 +1749,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -2243,8 +2243,8 @@ "required": false, "in": "query", "description": "Permissions to remove (format: resource.action). Supports comma-separated values as well as repeated query params.", + "example": "?permissions=eventType.read,booking.read", "schema": { - "example": "?permissions=eventType.read,booking.read", "type": "array", "items": { "type": "string", @@ -2509,8 +2509,8 @@ "required": false, "in": "query", "description": "Filter by teamIds. Team ids must be separated by a comma.", + "example": "?teamIds=100,200", "schema": { - "example": "?teamIds=100,200", "type": "array", "items": { "type": "number" @@ -2709,8 +2709,8 @@ "required": true, "in": "query", "description": "\n Time starting from which available slots should be checked.\n \n Must be in UTC timezone as ISO 8601 datestring.\n \n You can pass date without hours which defaults to start of day or specify hours:\n 2024-08-13 (will have hours 00:00:00 aka at very beginning of the date) or you can specify hours manually like 2024-08-13T09:00:00Z\n ", + "example": "2050-09-05", "schema": { - "example": "2050-09-05", "type": "string" } }, @@ -2719,8 +2719,8 @@ "required": true, "in": "query", "description": "\n Time until which available slots should be checked.\n \n Must be in UTC timezone as ISO 8601 datestring.\n \n You can pass date without hours which defaults to end of day or specify hours:\n 2024-08-20 (will have hours 23:59:59 aka at the very end of the date) or you can specify hours manually like 2024-08-20T18:00:00Z", + "example": "2050-09-06", "schema": { - "example": "2050-09-06", "type": "string" } }, @@ -2729,8 +2729,8 @@ "required": false, "in": "query", "description": "Time zone in which the available slots should be returned. Defaults to UTC.", + "example": "Europe/Rome", "schema": { - "example": "Europe/Rome", "type": "string" } }, @@ -2739,8 +2739,8 @@ "required": false, "in": "query", "description": "If event type has multiple possible durations then you can specify the desired duration here. Also, if you are fetching slots for a dynamic event then you can specify the duration her which defaults to 30, meaning that returned slots will be each 30 minutes long.", + "example": "60", "schema": { - "example": "60", "type": "number" } }, @@ -2749,8 +2749,8 @@ "required": false, "in": "query", "description": "Format of slot times in response. Use 'range' to get start and end times.", + "example": "range", "schema": { - "example": "range", "enum": [ "range", "time" @@ -2763,8 +2763,8 @@ "required": false, "in": "query", "description": "The unique identifier of the booking being rescheduled. When provided will ensure that the original booking time appears within the returned available slots when rescheduling.", + "example": "abc123def456", "schema": { - "example": "abc123def456", "type": "string" } }, @@ -2773,8 +2773,8 @@ "required": false, "in": "query", "description": "Whether to queue the form response.", + "example": true, "schema": { - "example": true, "type": "boolean" } } @@ -2907,11 +2907,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -2920,10 +2920,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -2990,11 +2990,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -3003,10 +3003,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -3139,11 +3139,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -3152,10 +3152,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -3402,8 +3402,8 @@ "required": false, "in": "query", "description": "Filter bookings by status. If you want to filter by multiple statuses, separate them with a comma.", + "example": "?status=upcoming,past", "schema": { - "example": "?status=upcoming,past", "type": "array", "items": { "type": "string", @@ -3422,8 +3422,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's email address.", + "example": "example@domain.com", "schema": { - "example": "example@domain.com", "type": "string" } }, @@ -3432,8 +3432,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's name.", + "example": "John Doe", "schema": { - "example": "John Doe", "type": "string" } }, @@ -3442,8 +3442,8 @@ "required": false, "in": "query", "description": "Filter bookings by the booking Uid.", + "example": "2NtaeaVcKfpmSZ4CthFdfk", "schema": { - "example": "2NtaeaVcKfpmSZ4CthFdfk", "type": "string" } }, @@ -3452,8 +3452,8 @@ "required": false, "in": "query", "description": "Filter bookings by event type ids belonging to the team. Event type ids must be separated by a comma.", + "example": "?eventTypeIds=100,200", "schema": { - "example": "?eventTypeIds=100,200", "type": "string" } }, @@ -3462,8 +3462,8 @@ "required": false, "in": "query", "description": "Filter bookings by event type id belonging to the team.", + "example": "?eventTypeId=100", "schema": { - "example": "?eventTypeId=100", "type": "string" } }, @@ -3472,8 +3472,8 @@ "required": false, "in": "query", "description": "Filter bookings with start after this date string.", + "example": "?afterStart=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterStart=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -3482,8 +3482,8 @@ "required": false, "in": "query", "description": "Filter bookings with end before this date string.", + "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "schema": { - "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "type": "string" } }, @@ -3492,8 +3492,8 @@ "required": false, "in": "query", "description": "Sort results by their start time in ascending or descending order.", + "example": "?sortStart=asc OR ?sortStart=desc", "schema": { - "example": "?sortStart=asc OR ?sortStart=desc", "enum": [ "asc", "desc" @@ -3506,8 +3506,8 @@ "required": false, "in": "query", "description": "Sort results by their end time in ascending or descending order.", + "example": "?sortEnd=asc OR ?sortEnd=desc", "schema": { - "example": "?sortEnd=asc OR ?sortEnd=desc", "enum": [ "asc", "desc" @@ -3520,8 +3520,8 @@ "required": false, "in": "query", "description": "Sort results by their creation time (when booking was made) in ascending or descending order.", + "example": "?sortCreated=asc OR ?sortCreated=desc", "schema": { - "example": "?sortCreated=asc OR ?sortCreated=desc", "enum": [ "asc", "desc" @@ -3534,10 +3534,10 @@ "required": false, "in": "query", "description": "The number of items to return", + "example": 10, "schema": { "minimum": 1, "maximum": 250, - "example": 10, "type": "number" } }, @@ -3546,9 +3546,9 @@ "required": false, "in": "query", "description": "The number of items to skip", + "example": 0, "schema": { "minimum": 0, - "example": 0, "type": "number" } }, @@ -3631,8 +3631,8 @@ "required": false, "in": "query", "description": "Filter booking references by type", + "example": "google_calendar", "schema": { - "example": "google_calendar", "enum": [ "google_calendar", "office365_calendar", @@ -4503,11 +4503,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -4516,10 +4516,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -4959,11 +4959,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -4972,10 +4972,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -5426,11 +5426,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -5439,10 +5439,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -5989,8 +5989,8 @@ "required": false, "in": "query", "description": "Permissions to remove (format: resource.action). Supports comma-separated values as well as repeated query params.", + "example": "?permissions=eventType.read,booking.read", "schema": { - "example": "?permissions=eventType.read,booking.read", "type": "array", "items": { "type": "string", @@ -6453,8 +6453,8 @@ "required": true, "in": "query", "description": "\n Time starting from which available slots should be checked.\n \n Must be in UTC timezone as ISO 8601 datestring.\n \n You can pass date without hours which defaults to start of day or specify hours:\n 2024-08-13 (will have hours 00:00:00 aka at very beginning of the date) or you can specify hours manually like 2024-08-13T09:00:00Z\n ", + "example": "2050-09-05", "schema": { - "example": "2050-09-05", "type": "string" } }, @@ -6463,8 +6463,8 @@ "required": true, "in": "query", "description": "\n Time until which available slots should be checked.\n \n Must be in UTC timezone as ISO 8601 datestring.\n \n You can pass date without hours which defaults to end of day or specify hours:\n 2024-08-20 (will have hours 23:59:59 aka at the very end of the date) or you can specify hours manually like 2024-08-20T18:00:00Z", + "example": "2050-09-06", "schema": { - "example": "2050-09-06", "type": "string" } }, @@ -6473,8 +6473,8 @@ "required": false, "in": "query", "description": "Time zone in which the available slots should be returned. Defaults to UTC.", + "example": "Europe/Rome", "schema": { - "example": "Europe/Rome", "type": "string" } }, @@ -6483,8 +6483,8 @@ "required": false, "in": "query", "description": "If event type has multiple possible durations then you can specify the desired duration here. Also, if you are fetching slots for a dynamic event then you can specify the duration her which defaults to 30, meaning that returned slots will be each 30 minutes long.", + "example": "60", "schema": { - "example": "60", "type": "number" } }, @@ -6493,8 +6493,8 @@ "required": false, "in": "query", "description": "Format of slot times in response. Use 'range' to get start and end times.", + "example": "range", "schema": { - "example": "range", "enum": [ "range", "time" @@ -6507,8 +6507,8 @@ "required": false, "in": "query", "description": "The unique identifier of the booking being rescheduled. When provided will ensure that the original booking time appears within the returned available slots when rescheduling.", + "example": "abc123def456", "schema": { - "example": "abc123def456", "type": "string" } }, @@ -6517,8 +6517,8 @@ "required": false, "in": "query", "description": "Whether to queue the form response.", + "example": true, "schema": { - "example": true, "type": "boolean" } } @@ -6659,11 +6659,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -6672,10 +6672,20 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, + "type": "number" + } + }, + { + "name": "eventTypeId", + "required": false, + "in": "query", + "description": "Filter schedules by event type ID", + "example": 1, + "schema": { "type": "number" } } @@ -6893,6 +6903,16 @@ "schema": { "type": "number" } + }, + { + "name": "eventTypeId", + "required": false, + "in": "query", + "description": "Filter schedules by event type ID", + "example": 1, + "schema": { + "type": "number" + } } ], "responses": { @@ -6965,11 +6985,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -6978,10 +6998,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -7122,11 +7142,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -7135,10 +7155,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -7665,10 +7685,10 @@ "required": false, "in": "query", "description": "The number of items to return", + "example": 10, "schema": { "minimum": 1, "maximum": 1000, - "example": 10, "type": "number" } }, @@ -7677,9 +7697,9 @@ "required": false, "in": "query", "description": "The number of items to skip", + "example": 0, "schema": { "minimum": 0, - "example": 0, "type": "number" } }, @@ -7688,11 +7708,11 @@ "required": false, "in": "query", "description": "The email address or an array of email addresses to filter by", + "example": [ + "user1@example.com", + "user2@example.com" + ], "schema": { - "example": [ - "user1@example.com", - "user2@example.com" - ], "type": "array", "items": { "type": "string" @@ -7704,8 +7724,8 @@ "required": false, "in": "query", "description": "Filter by assigned attribute option ids. ids must be separated by a comma.", + "example": "?assignedOptionIds=aaaaaaaa-bbbb-cccc-dddd-eeeeee1eee,aaaaaaaa-bbbb-cccc-dddd-eeeeee2eee", "schema": { - "example": "?assignedOptionIds=aaaaaaaa-bbbb-cccc-dddd-eeeeee1eee,aaaaaaaa-bbbb-cccc-dddd-eeeeee2eee", "type": "array", "items": { "type": "string" @@ -7717,9 +7737,9 @@ "required": false, "in": "query", "description": "Query operator used to filter assigned options, AND by default.", + "example": "NONE", "schema": { "default": "AND", - "example": "NONE", "enum": [ "OR", "AND", @@ -7733,8 +7753,8 @@ "required": false, "in": "query", "description": "Filter by teamIds. Team ids must be separated by a comma.", + "example": "?teamIds=100,200", "schema": { - "example": "?teamIds=100,200", "type": "array", "items": { "type": "number" @@ -8010,8 +8030,8 @@ "required": false, "in": "query", "description": "Filter bookings by status. If you want to filter by multiple statuses, separate them with a comma.", + "example": "?status=upcoming,past", "schema": { - "example": "?status=upcoming,past", "type": "array", "items": { "type": "string", @@ -8030,8 +8050,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's email address.", + "example": "example@domain.com", "schema": { - "example": "example@domain.com", "type": "string" } }, @@ -8040,8 +8060,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's name.", + "example": "John Doe", "schema": { - "example": "John Doe", "type": "string" } }, @@ -8050,8 +8070,8 @@ "required": false, "in": "query", "description": "Filter bookings by the booking Uid.", + "example": "2NtaeaVcKfpmSZ4CthFdfk", "schema": { - "example": "2NtaeaVcKfpmSZ4CthFdfk", "type": "string" } }, @@ -8060,8 +8080,8 @@ "required": false, "in": "query", "description": "Filter bookings by event type ids belonging to the user. Event type ids must be separated by a comma.", + "example": "?eventTypeIds=100,200", "schema": { - "example": "?eventTypeIds=100,200", "type": "string" } }, @@ -8070,8 +8090,8 @@ "required": false, "in": "query", "description": "Filter bookings by event type id belonging to the user.", + "example": "?eventTypeId=100", "schema": { - "example": "?eventTypeId=100", "type": "string" } }, @@ -8080,8 +8100,8 @@ "required": false, "in": "query", "description": "Filter bookings by team ids that user is part of. Team ids must be separated by a comma.", + "example": "?teamIds=50,60", "schema": { - "example": "?teamIds=50,60", "type": "string" } }, @@ -8090,8 +8110,8 @@ "required": false, "in": "query", "description": "Filter bookings by team id that user is part of", + "example": "?teamId=50", "schema": { - "example": "?teamId=50", "type": "string" } }, @@ -8100,8 +8120,8 @@ "required": false, "in": "query", "description": "Filter bookings with start after this date string.", + "example": "?afterStart=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterStart=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -8110,8 +8130,8 @@ "required": false, "in": "query", "description": "Filter bookings with end before this date string.", + "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "schema": { - "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "type": "string" } }, @@ -8120,8 +8140,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been created after this date string.", + "example": "?afterCreatedAt=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterCreatedAt=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -8130,8 +8150,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been created before this date string.", + "example": "?beforeCreatedAt=2025-03-14T11:00:00.000Z", "schema": { - "example": "?beforeCreatedAt=2025-03-14T11:00:00.000Z", "type": "string" } }, @@ -8140,8 +8160,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been updated after this date string.", + "example": "?afterUpdatedAt=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterUpdatedAt=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -8150,8 +8170,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been updated before this date string.", + "example": "?beforeUpdatedAt=2025-03-14T11:00:00.000Z", "schema": { - "example": "?beforeUpdatedAt=2025-03-14T11:00:00.000Z", "type": "string" } }, @@ -8160,8 +8180,8 @@ "required": false, "in": "query", "description": "Sort results by their start time in ascending or descending order.", + "example": "?sortStart=asc OR ?sortStart=desc", "schema": { - "example": "?sortStart=asc OR ?sortStart=desc", "enum": [ "asc", "desc" @@ -8174,8 +8194,8 @@ "required": false, "in": "query", "description": "Sort results by their end time in ascending or descending order.", + "example": "?sortEnd=asc OR ?sortEnd=desc", "schema": { - "example": "?sortEnd=asc OR ?sortEnd=desc", "enum": [ "asc", "desc" @@ -8188,8 +8208,8 @@ "required": false, "in": "query", "description": "Sort results by their creation time (when booking was made) in ascending or descending order.", + "example": "?sortCreated=asc OR ?sortCreated=desc", "schema": { - "example": "?sortCreated=asc OR ?sortCreated=desc", "enum": [ "asc", "desc" @@ -8202,8 +8222,8 @@ "required": false, "in": "query", "description": "Sort results by their updated time (for example when booking status changes) in ascending or descending order.", + "example": "?sortUpdated=asc OR ?sortUpdated=desc", "schema": { - "example": "?sortUpdated=asc OR ?sortUpdated=desc", "enum": [ "asc", "desc" @@ -8216,9 +8236,9 @@ "required": false, "in": "query", "description": "The number of items to return", + "example": 10, "schema": { "default": 100, - "example": 10, "type": "number" } }, @@ -8227,9 +8247,9 @@ "required": false, "in": "query", "description": "The number of items to skip", + "example": 0, "schema": { "default": 0, - "example": 0, "type": "number" } } @@ -8289,11 +8309,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -8302,10 +8322,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -8314,8 +8334,8 @@ "required": false, "in": "query", "description": "Sort results by their start time in ascending or descending order.", + "example": "?sortStart=asc OR ?sortStart=desc", "schema": { - "example": "?sortStart=asc OR ?sortStart=desc", "enum": [ "asc", "desc" @@ -8328,8 +8348,8 @@ "required": false, "in": "query", "description": "Sort results by their end time in ascending or descending order.", + "example": "?sortEnd=asc OR ?sortEnd=desc", "schema": { - "example": "?sortEnd=asc OR ?sortEnd=desc", "enum": [ "asc", "desc" @@ -8570,11 +8590,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -8583,10 +8603,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -8595,8 +8615,8 @@ "required": false, "in": "query", "description": "Sort results by their start time in ascending or descending order.", + "example": "?sortStart=asc OR ?sortStart=desc", "schema": { - "example": "?sortStart=asc OR ?sortStart=desc", "enum": [ "asc", "desc" @@ -8609,8 +8629,8 @@ "required": false, "in": "query", "description": "Sort results by their end time in ascending or descending order.", + "example": "?sortEnd=asc OR ?sortEnd=desc", "schema": { - "example": "?sortEnd=asc OR ?sortEnd=desc", "enum": [ "asc", "desc" @@ -8623,8 +8643,8 @@ "required": false, "in": "query", "description": "Filter ooo entries by the user email address. user must be within your organization.", + "example": "example@domain.com", "schema": { - "example": "example@domain.com", "type": "string" } } @@ -9012,11 +9032,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -9025,10 +9045,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -9440,8 +9460,8 @@ "required": false, "in": "query", "description": "Filter bookings by status. If you want to filter by multiple statuses, separate them with a comma.", + "example": "?status=upcoming,past", "schema": { - "example": "?status=upcoming,past", "type": "array", "items": { "type": "string", @@ -9460,8 +9480,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's email address.", + "example": "example@domain.com", "schema": { - "example": "example@domain.com", "type": "string" } }, @@ -9470,8 +9490,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's name.", + "example": "John Doe", "schema": { - "example": "John Doe", "type": "string" } }, @@ -9480,8 +9500,8 @@ "required": false, "in": "query", "description": "Filter bookings by the booking Uid.", + "example": "2NtaeaVcKfpmSZ4CthFdfk", "schema": { - "example": "2NtaeaVcKfpmSZ4CthFdfk", "type": "string" } }, @@ -9490,8 +9510,8 @@ "required": false, "in": "query", "description": "Filter bookings by event type ids belonging to the user. Event type ids must be separated by a comma.", + "example": "?eventTypeIds=100,200", "schema": { - "example": "?eventTypeIds=100,200", "type": "string" } }, @@ -9500,8 +9520,8 @@ "required": false, "in": "query", "description": "Filter bookings by event type id belonging to the user.", + "example": "?eventTypeId=100", "schema": { - "example": "?eventTypeId=100", "type": "string" } }, @@ -9510,8 +9530,8 @@ "required": false, "in": "query", "description": "Filter bookings by team ids that user is part of. Team ids must be separated by a comma.", + "example": "?teamIds=50,60", "schema": { - "example": "?teamIds=50,60", "type": "string" } }, @@ -9520,8 +9540,8 @@ "required": false, "in": "query", "description": "Filter bookings by team id that user is part of", + "example": "?teamId=50", "schema": { - "example": "?teamId=50", "type": "string" } }, @@ -9530,8 +9550,8 @@ "required": false, "in": "query", "description": "Filter bookings with start after this date string.", + "example": "?afterStart=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterStart=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -9540,8 +9560,8 @@ "required": false, "in": "query", "description": "Filter bookings with end before this date string.", + "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "schema": { - "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "type": "string" } }, @@ -9550,8 +9570,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been created after this date string.", + "example": "?afterCreatedAt=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterCreatedAt=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -9560,8 +9580,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been created before this date string.", + "example": "?beforeCreatedAt=2025-03-14T11:00:00.000Z", "schema": { - "example": "?beforeCreatedAt=2025-03-14T11:00:00.000Z", "type": "string" } }, @@ -9570,8 +9590,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been updated after this date string.", + "example": "?afterUpdatedAt=2025-03-07T10:00:00.000Z", "schema": { - "example": "?afterUpdatedAt=2025-03-07T10:00:00.000Z", "type": "string" } }, @@ -9580,8 +9600,8 @@ "required": false, "in": "query", "description": "Filter bookings that have been updated before this date string.", + "example": "?beforeUpdatedAt=2025-03-14T11:00:00.000Z", "schema": { - "example": "?beforeUpdatedAt=2025-03-14T11:00:00.000Z", "type": "string" } }, @@ -9590,8 +9610,8 @@ "required": false, "in": "query", "description": "Sort results by their start time in ascending or descending order.", + "example": "?sortStart=asc OR ?sortStart=desc", "schema": { - "example": "?sortStart=asc OR ?sortStart=desc", "enum": [ "asc", "desc" @@ -9604,8 +9624,8 @@ "required": false, "in": "query", "description": "Sort results by their end time in ascending or descending order.", + "example": "?sortEnd=asc OR ?sortEnd=desc", "schema": { - "example": "?sortEnd=asc OR ?sortEnd=desc", "enum": [ "asc", "desc" @@ -9618,8 +9638,8 @@ "required": false, "in": "query", "description": "Sort results by their creation time (when booking was made) in ascending or descending order.", + "example": "?sortCreated=asc OR ?sortCreated=desc", "schema": { - "example": "?sortCreated=asc OR ?sortCreated=desc", "enum": [ "asc", "desc" @@ -9632,8 +9652,8 @@ "required": false, "in": "query", "description": "Sort results by their updated time (for example when booking status changes) in ascending or descending order.", + "example": "?sortUpdated=asc OR ?sortUpdated=desc", "schema": { - "example": "?sortUpdated=asc OR ?sortUpdated=desc", "enum": [ "asc", "desc" @@ -9646,9 +9666,9 @@ "required": false, "in": "query", "description": "The number of items to return", + "example": 10, "schema": { "default": 100, - "example": 10, "type": "number" } }, @@ -9657,9 +9677,9 @@ "required": false, "in": "query", "description": "The number of items to skip", + "example": 0, "schema": { "default": 0, - "example": 0, "type": "number" } }, @@ -10408,8 +10428,8 @@ "required": false, "in": "query", "description": "Filter booking references by type", + "example": "google_calendar", "schema": { - "example": "google_calendar", "enum": [ "google_calendar", "office365_calendar", @@ -10813,15 +10833,26 @@ "get": { "operationId": "CalendarsController_getBusyTimes", "summary": "Get busy times", - "description": "Get busy times from a calendar. Example request URL is `https://api.cal.com/v2/calendars/busy-times?loggedInUsersTz=Europe%2FMadrid&dateFrom=2024-12-18&dateTo=2024-12-18&calendarsToLoad[0][credentialId]=135&calendarsToLoad[0][externalId]=skrauciz%40gmail.com`", + "description": "Get busy times from a calendar. Example request URL is `https://api.cal.com/v2/calendars/busy-times?timeZone=Europe%2FMadrid&dateFrom=2024-12-18&dateTo=2024-12-18&calendarsToLoad[0][credentialId]=135&calendarsToLoad[0][externalId]=skrauciz%40gmail.com`. Note: loggedInUsersTz is deprecated, use timeZone instead.", "parameters": [ { "name": "loggedInUsersTz", - "required": true, + "required": false, "in": "query", - "description": "The timezone of the logged in user represented as a string", + "deprecated": true, + "description": "Deprecated: Use timeZone instead. The timezone of the user represented as a string", + "example": "America/New_York", + "schema": { + "type": "string" + } + }, + { + "name": "timeZone", + "required": false, + "in": "query", + "description": "The timezone for the busy times query represented as a string", + "example": "America/New_York", "schema": { - "example": "America/New_York", "type": "string" } }, @@ -10830,8 +10861,8 @@ "required": false, "in": "query", "description": "The starting date for the busy times query", + "example": "2023-10-01", "schema": { - "example": "2023-10-01", "type": "string" } }, @@ -10840,8 +10871,8 @@ "required": false, "in": "query", "description": "The ending date for the busy times query", + "example": "2023-10-31", "schema": { - "example": "2023-10-31", "type": "string" } }, @@ -11506,8 +11537,8 @@ "required": false, "in": "query", "description": "The number of items to return", + "example": 10, "schema": { - "example": 10, "type": "number" } }, @@ -11516,8 +11547,8 @@ "required": false, "in": "query", "description": "The number of items to skip", + "example": 0, "schema": { - "example": 0, "type": "number" } }, @@ -11526,8 +11557,8 @@ "required": false, "in": "query", "description": "Filter managed users by email. If you want to filter by multiple emails, separate them with a comma.", + "example": "?emails=email1@example.com,email2@example.com", "schema": { - "example": "?emails=email1@example.com,email2@example.com", "type": "array", "items": { "type": "string" @@ -11931,11 +11962,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -11944,10 +11975,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -12770,11 +12801,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -12783,10 +12814,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -13243,11 +13274,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -13256,10 +13287,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -13267,9 +13298,9 @@ "name": "slug", "required": false, "in": "query", + "example": "organization-slug", "description": "The slug of the managed organization", "schema": { - "example": "organization-slug", "type": "string" } }, @@ -13277,9 +13308,9 @@ "name": "metadataKey", "required": false, "in": "query", + "example": "metadata-key", "description": "The key of the metadata - it is case sensitive so provide exactly as stored. If you provide it then you must also provide metadataValue", "schema": { - "example": "metadata-key", "type": "string" } }, @@ -13287,9 +13318,9 @@ "name": "metadataValue", "required": false, "in": "query", + "example": "metadata-value", "description": "The value of the metadata - it is case sensitive so provide exactly as stored. If you provide it then you must also provide metadataKey", "schema": { - "example": "metadata-value", "type": "string" } } @@ -13754,11 +13785,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -13767,10 +13798,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -13819,11 +13850,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -13832,10 +13863,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -13982,8 +14013,8 @@ "required": true, "in": "query", "description": "\n Time starting from which available slots should be checked.\n \n Must be in UTC timezone as ISO 8601 datestring.\n \n You can pass date without hours which defaults to start of day or specify hours:\n 2024-08-13 (will have hours 00:00:00 aka at very beginning of the date) or you can specify hours manually like 2024-08-13T09:00:00Z\n ", + "example": "2050-09-05", "schema": { - "example": "2050-09-05", "type": "string" } }, @@ -13992,8 +14023,8 @@ "required": true, "in": "query", "description": "\n Time until which available slots should be checked.\n \n Must be in UTC timezone as ISO 8601 datestring.\n \n You can pass date without hours which defaults to end of day or specify hours:\n 2024-08-20 (will have hours 23:59:59 aka at the very end of the date) or you can specify hours manually like 2024-08-20T18:00:00Z", + "example": "2050-09-06", "schema": { - "example": "2050-09-06", "type": "string" } }, @@ -14002,8 +14033,8 @@ "required": false, "in": "query", "description": "Time zone in which the available slots should be returned. Defaults to UTC.", + "example": "Europe/Rome", "schema": { - "example": "Europe/Rome", "type": "string" } }, @@ -14012,8 +14043,8 @@ "required": false, "in": "query", "description": "If event type has multiple possible durations then you can specify the desired duration here. Also, if you are fetching slots for a dynamic event then you can specify the duration her which defaults to 30, meaning that returned slots will be each 30 minutes long.", + "example": "60", "schema": { - "example": "60", "type": "number" } }, @@ -14022,8 +14053,8 @@ "required": false, "in": "query", "description": "Format of slot times in response. Use 'range' to get start and end times.", + "example": "range", "schema": { - "example": "range", "enum": [ "range", "time" @@ -14036,8 +14067,8 @@ "required": false, "in": "query", "description": "The unique identifier of the booking being rescheduled. When provided will ensure that the original booking time appears within the returned available slots when rescheduling.", + "example": "abc123def456", "schema": { - "example": "abc123def456", "type": "string" } }, @@ -14488,108 +14519,96 @@ "required": false, "in": "query", "description": "The unique identifier of the booking being rescheduled. When provided will ensure that the original booking time appears within the returned available slots when rescheduling.", - "schema": { - "example": "abc123def456" - } + "example": "abc123def456", + "schema": {} }, { "name": "start", "required": true, "in": "query", "description": "\n Time starting from which available slots should be checked.\n\n Must be in UTC timezone as ISO 8601 datestring.\n\n You can pass date without hours which defaults to start of day or specify hours:\n 2024-08-13 (will have hours 00:00:00 aka at very beginning of the date) or you can specify hours manually like 2024-08-13T09:00:00Z.", - "schema": { - "example": "2050-09-05" - } + "example": "2050-09-05", + "schema": {} }, { "name": "end", "required": true, "in": "query", "description": "\n Time until which available slots should be checked.\n\n Must be in UTC timezone as ISO 8601 datestring.\n\n You can pass date without hours which defaults to end of day or specify hours:\n 2024-08-20 (will have hours 23:59:59 aka at the very end of the date) or you can specify hours manually like 2024-08-20T18:00:00Z.", - "schema": { - "example": "2050-09-06" - } + "example": "2050-09-06", + "schema": {} }, { "name": "organizationSlug", "required": false, "in": "query", "description": "The slug of the organization to which user with username belongs or team with teamSlug belongs.", - "schema": { - "example": "org-slug" - } + "example": "org-slug", + "schema": {} }, { "name": "teamSlug", "required": false, "in": "query", "description": "The slug of the team who owns event type with eventTypeSlug - used when slots are checked for team event type.", - "schema": { - "example": "team-slug" - } + "example": "team-slug", + "schema": {} }, { "name": "username", "required": false, "in": "query", "description": "The username of the user who owns event type with eventTypeSlug - used when slots are checked for individual user event type.", - "schema": { - "example": "bob" - } + "example": "bob", + "schema": {} }, { "name": "eventTypeSlug", "required": false, "in": "query", "description": "The slug of the event type for which available slots should be checked. If slug is provided then username or teamSlug must be provided too and if relevant organizationSlug too.", - "schema": { - "example": "event-type-slug" - } + "example": "event-type-slug", + "schema": {} }, { "name": "eventTypeId", "required": false, "in": "query", "description": "The ID of the event type for which available slots should be checked.", - "schema": { - "example": "100" - } + "example": "100", + "schema": {} }, { "name": "usernames", "required": false, "in": "query", "description": "The usernames for which available slots should be checked separated by a comma.\n\n Checking slots by usernames is used mainly for dynamic events where there is no specific event but we just want to know when 2 or more people are available.\n\n Must contain at least 2 usernames.", - "schema": { - "example": "alice,bob" - } + "example": "alice,bob", + "schema": {} }, { "name": "format", "required": false, "in": "query", "description": "Format of slot times in response. Use 'range' to get start and end times. Use 'time' or omit this query parameter to get only start time.", - "schema": { - "example": "range" - } + "example": "range", + "schema": {} }, { "name": "duration", "required": false, "in": "query", "description": "If event type has multiple possible durations then you can specify the desired duration here. Also, if you are fetching slots for a dynamic event then you can specify the duration her which defaults to 30, meaning that returned slots will be each 30 minutes long.", - "schema": { - "example": "60" - } + "example": "60", + "schema": {} }, { "name": "timeZone", "required": false, "in": "query", "description": "Time zone in which the available slots should be returned. Defaults to UTC.", - "schema": { - "example": "Europe/Rome" - } + "example": "Europe/Rome", + "schema": {} } ], "responses": { @@ -15201,8 +15220,8 @@ "required": false, "in": "query", "description": "Filter bookings by status. If you want to filter by multiple statuses, separate them with a comma.", + "example": "?status=upcoming,past", "schema": { - "example": "?status=upcoming,past", "type": "array", "items": { "type": "string", @@ -15221,8 +15240,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's email address.", + "example": "example@domain.com", "schema": { - "example": "example@domain.com", "type": "string" } }, @@ -15231,8 +15250,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's name.", + "example": "John Doe", "schema": { - "example": "John Doe", "type": "string" } }, @@ -15241,8 +15260,8 @@ "required": false, "in": "query", "description": "Filter bookings by the booking Uid.", + "example": "2NtaeaVcKfpmSZ4CthFdfk", "schema": { - "example": "2NtaeaVcKfpmSZ4CthFdfk", "type": "string" } }, @@ -15251,8 +15270,18 @@ "required": false, "in": "query", "description": "Filter bookings by event type ids belonging to the team. Event type ids must be separated by a comma.", + "example": "?eventTypeIds=100,200", + "schema": { + "type": "string" + } + }, + { + "name": "eventTypeId", + "required": false, + "in": "query", + "description": "Filter bookings by event type id belonging to the team.", + "example": "?eventTypeId=100", "schema": { - "example": "100,200", "type": "string" } }, @@ -15260,9 +15289,9 @@ "name": "afterStart", "required": false, "in": "query", - "description": "Filter bookings that start after this date-time (ISO 8601).", + "description": "Filter bookings with start after this date string.", + "example": "?afterStart=2025-03-07T10:00:00.000Z", "schema": { - "example": "2024-08-13T10:00:00.000Z", "type": "string" } }, @@ -15270,29 +15299,9 @@ "name": "beforeEnd", "required": false, "in": "query", - "description": "Filter bookings that end before this date-time (ISO 8601).", + "description": "Filter bookings with end before this date string.", + "example": "?beforeEnd=2025-03-07T11:00:00.000Z", "schema": { - "example": "2024-08-20T10:00:00.000Z", - "type": "string" - } - }, - { - "name": "teamMemberIds", - "required": false, - "in": "query", - "description": "Filter bookings by team member user ids. Multiple ids can be separated by a comma. Only works for team events.", - "schema": { - "example": "10,20", - "type": "string" - } - }, - { - "name": "teamMemberEmails", - "required": false, - "in": "query", - "description": "Filter bookings by team member emails. Multiple emails can be separated by a comma. Only works for team events.", - "schema": { - "example": "alice@example.com,bob@example.com", "type": "string" } }, @@ -15300,9 +15309,9 @@ "name": "sortStart", "required": false, "in": "query", - "description": "Sort results by their start time (when booking is scheduled for) in ascending or descending order.", + "description": "Sort results by their start time in ascending or descending order.", + "example": "?sortStart=asc OR ?sortStart=desc", "schema": { - "example": "?sortStart=asc OR ?sortStart=desc", "enum": [ "asc", "desc" @@ -15314,9 +15323,9 @@ "name": "sortEnd", "required": false, "in": "query", - "description": "Sort results by their end time (when booking is scheduled to end) in ascending or descending order.", + "description": "Sort results by their end time in ascending or descending order.", + "example": "?sortEnd=asc OR ?sortEnd=desc", "schema": { - "example": "?sortEnd=asc OR ?sortEnd=desc", "enum": [ "asc", "desc" @@ -15329,8 +15338,8 @@ "required": false, "in": "query", "description": "Sort results by their creation time (when booking was made) in ascending or descending order.", + "example": "?sortCreated=asc OR ?sortCreated=desc", "schema": { - "example": "?sortCreated=asc OR ?sortCreated=desc", "enum": [ "asc", "desc" @@ -15343,10 +15352,10 @@ "required": false, "in": "query", "description": "The number of items to return", + "example": 10, "schema": { "minimum": 1, "maximum": 250, - "example": 10, "type": "number" } }, @@ -15355,9 +15364,9 @@ "required": false, "in": "query", "description": "The number of items to skip", + "example": 0, "schema": { "minimum": 0, - "example": 0, "type": "number" } }, @@ -15781,11 +15790,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -15794,10 +15803,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -16083,11 +16092,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -16096,10 +16105,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -16108,8 +16117,8 @@ "required": false, "in": "query", "description": "Filter team memberships by email addresses. If you want to filter by multiple emails, separate them with a comma (max 20 emails for performance).", + "example": "?emails=user1@example.com,user2@example.com", "schema": { - "example": "?emails=user1@example.com,user2@example.com", "type": "array", "items": { "type": "string" @@ -16311,11 +16320,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -16324,10 +16333,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } @@ -16555,11 +16564,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -16568,10 +16577,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -16620,11 +16629,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -16633,10 +16642,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -16945,11 +16954,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -16958,10 +16967,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -17002,11 +17011,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -17015,10 +17024,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } }, @@ -17189,11 +17198,11 @@ "required": false, "in": "query", "description": "Maximum number of items to return", + "example": 25, "schema": { "minimum": 1, "maximum": 250, "default": 250, - "example": 25, "type": "number" } }, @@ -17202,10 +17211,10 @@ "required": false, "in": "query", "description": "Number of items to skip", + "example": 0, "schema": { "minimum": 0, "default": 0, - "example": 0, "type": "number" } } diff --git a/packages/platform/libraries/package.json b/packages/platform/libraries/package.json index 6e9bbaebdb..84fa257837 100644 --- a/packages/platform/libraries/package.json +++ b/packages/platform/libraries/package.json @@ -104,6 +104,11 @@ "import": "./dist/errors.js", "require": "./dist/errors.cjs", "types": "./dist/errors.d.ts" + }, + "./calendars": { + "import": "./dist/calendars.js", + "require": "./dist/calendars.cjs", + "types": "./dist/calendars.d.ts" } }, "typesVersions": { @@ -146,6 +151,9 @@ ], "errors": [ "dist/errors.d.ts" + ], + "calendars": [ + "dist/calendars.d.ts" ] } } diff --git a/packages/platform/libraries/vite.config.js b/packages/platform/libraries/vite.config.js index 5b9a4c207e..e8896ee716 100644 --- a/packages/platform/libraries/vite.config.js +++ b/packages/platform/libraries/vite.config.js @@ -43,6 +43,7 @@ export default defineConfig({ "private-links": resolve(__dirname, "./private-links.ts"), pbac: resolve(__dirname, "./pbac.ts"), errors: resolve(__dirname, "./errors.ts"), + calendars: resolve(__dirname, "./calendars.ts"), }, name: "calcom-lib", fileName: "calcom-lib",