diff --git a/AGENTS.md b/AGENTS.md index de69b15999b768..879c978338fdb5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,239 +1,103 @@ -# Cal.com Development Guide for AI Agents +# Compliance Rules -You are a senior Cal.com engineer working in a Yarn/Turbo monorepo. You prioritize type safety, security, and small, reviewable diffs. +This file contains the compliance and code quality rules for this repository. -## Do +## 1. Repository and Service Classes Must Follow Naming Conventions -- Use `select` instead of `include` in Prisma queries for performance and security -- Use `import type { X }` for TypeScript type imports -- Use early returns to reduce nesting: `if (!booking) return null;` -- Use `ErrorWithCode` for errors in non-tRPC files (services, repositories, utilities); use `TRPCError` only in tRPC routers -- Use conventional commits: `feat:`, `fix:`, `refactor:` -- Create PRs in draft mode by default -- Run `yarn type-check:ci --force` before concluding CI failures are unrelated to your changes -- Import directly from source files, not barrel files (e.g., `@calcom/ui/components/button` not `@calcom/ui`) -- Add translations to `apps/web/public/static/locales/en/common.json` for all UI strings -- Use `date-fns` or native `Date` instead of Day.js when timezone awareness isn't needed -- Put permission checks in `page.tsx`, never in `layout.tsx` -- Use `ast-grep` for searching if available; otherwise use `rg` (ripgrep), then fall back to `grep` -- Use Biome for formatting and linting - - -## Don't - -- Never use `as any` - use proper type-safe solutions instead -- Never expose `credential.key` field in API responses or queries -- Never commit secrets or API keys -- Never modify `*.generated.ts` files directly - they're created by app-store-cli -- Never put business logic in repositories - that belongs in Services -- Never use barrel imports from index.ts files -- Never skip running type checks before pushing -- Never create large PRs (>500 lines or >10 files) - split them instead - -## Commands - -### File-scoped (preferred for speed) - -```bash -# Type check - always run on changed files -yarn type-check:ci --force - -# Lint and format single file -yarn biome check --write path/to/file.tsx - -# Unit test specific file -yarn vitest run path/to/file.test.ts - -# Unit test specific file + specific test -yarn vitest run path/to/file.test.ts --testNamePattern="specific test name" - -# Integration test specific file -VITEST_MODE=integration yarn test path/to/file.integration-test.ts - -# Integration test specific file + specific test -VITEST_MODE=integration yarn test path/to/file.integration-test.ts --testNamePattern="specific test name" - -# E2E test specific file -PLAYWRIGHT_HEADLESS=1 yarn e2e path/to/file.e2e.ts - -# E2E test specific file + specific test -PLAYWRIGHT_HEADLESS=1 yarn e2e path/to/file.e2e.ts --grep "specific test name" -``` - -### Project-wide (use sparingly) - -```bash -# Development -yarn dev # Start dev server -yarn dx # Dev with database setup - -# Build & check -yarn build # Build all packages -yarn biome check --write . # Lint and format all -yarn type-check # Type check all - -# Tests (use TZ=UTC for consistency) -TZ=UTC yarn test # All unit tests -yarn e2e # All E2E tests - -# Database -yarn prisma generate # Regenerate types after schema changes -yarn workspace @calcom/prisma db-migrate # Run migrations -``` - -### Biome focused workflow -+ -```bash -yarn biome check --write . -yarn type-check:ci --force -``` - - -## Boundaries - -### Always do -- Run type check on changed files before committing -- Run relevant tests before pushing -- Use `select` in Prisma queries -- Follow conventional commits for PR titles -- Run Biome before pushing - -### Ask first -- Adding new dependencies -- Schema changes to `packages/prisma/schema.prisma` -- Changes affecting multiple packages -- Deleting files -- Running full build or E2E suites - -### Never do -- Commit secrets, API keys, or `.env` files -- Expose `credential.key` in any query -- Use `as any` type casting -- Force push or rebase shared branches -- Modify generated files directly - -## Project Structure - -``` -apps/web/ # Main Next.js application -packages/prisma/ # Database schema (schema.prisma) and migrations -packages/trpc/ # tRPC API layer (routers in server/routers/) -packages/ui/ # Shared UI components -packages/features/ # Feature-specific code -packages/app-store/ # Third-party integrations -packages/lib/ # Shared utilities -``` - -### Key files -- Routes: `apps/web/app/` (App Router) -- Database schema: `packages/prisma/schema.prisma` -- tRPC routers: `packages/trpc/server/routers/` -- Translations: `apps/web/public/static/locales/en/common.json` -- Workflow constants: `packages/features/ee/workflows/lib/constants.ts` - -## Tech Stack - -- **Framework**: Next.js 13+ (App Router in some areas) -- **Language**: TypeScript (strict) -- **Database**: PostgreSQL with Prisma ORM -- **API**: tRPC for type-safe APIs -- **Auth**: NextAuth.js -- **Styling**: Tailwind CSS -- **Testing**: Vitest (unit), Playwright (E2E) -- **i18n**: next-i18next - -## Code Examples - -### Good error handling - -```typescript -// Good - Descriptive error with context -throw new Error(`Unable to create booking: User ${userId} has no available time slots for ${date}`); - -// Bad - Generic error -throw new Error("Booking failed"); -``` - -For which error class to use (`ErrorWithCode` vs `TRPCError`) and concrete examples, see [Error Types in knowledge-base.md](agents/knowledge-base.md#error-types). - -### Good Prisma query - -```typescript -// Good - Use select for performance and security -const booking = await prisma.booking.findFirst({ - select: { - id: true, - title: true, - user: { - select: { - id: true, - name: true, - email: true, - } - } - } -}); - -// Bad - Include fetches all fields including sensitive ones -const booking = await prisma.booking.findFirst({ - include: { user: true } -}); -``` - -### Good imports - -```typescript -// Good - Type imports and direct paths -import type { User } from "@prisma/client"; -import { Button } from "@calcom/ui/components/button"; - -// Bad - Regular import for types, barrel imports -import { User } from "@prisma/client"; -import { Button } from "@calcom/ui"; -``` - -### API v2 Imports (apps/api/v2) - -When importing from `@calcom/features` or `@calcom/trpc` into `apps/api/v2`, **do not import directly** because the API v2 app's `tsconfig.json` doesn't have path mappings for these modules, which causes "module not found" errors. - -Instead, re-export from `packages/platform/libraries/index.ts` and import from `@calcom/platform-libraries`: - -```typescript -// Step 1: In packages/platform/libraries/index.ts, add the export -export { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; - -// Step 2: In apps/api/v2, import from platform-libraries -import { ProfileRepository } from "@calcom/platform-libraries"; - -// Bad - Direct import causes module not found error in apps/api/v2 -import { ProfileRepository } from "@calcom/features/profile/repositories/ProfileRepository"; -``` - -## PR Checklist - -- [ ] Title follows conventional commits: `feat(scope): description` -- [ ] Type check passes: `yarn type-check:ci --force` -- [ ] Lint passes: `yarn lint:fix` -- [ ] Relevant tests pass -- [ ] Diff is small and focused (<500 lines, <10 files) -- [ ] No secrets or API keys committed -- [ ] UI strings added to translation files -- [ ] Created as draft PR - -## When Stuck - -- Ask a clarifying question before making large speculative changes -- Propose a short plan for complex tasks -- Open a draft PR with notes if unsure about approach -- Fix type errors before test failures - they're often the root cause -- Run `yarn prisma generate` if you see missing enum/type errors - -## Extended Documentation - -For detailed information, see the `agents/` directory: - -- **[agents/README.md](agents/README.md)** - Architecture overview and patterns -- **[agents/rules/](agents/rules/)** - Modular engineering rules (performance, architecture, data layer, etc.) -- **[agents/commands.md](agents/commands.md)** - Complete command reference -- **[agents/knowledge-base.md](agents/knowledge-base.md)** - Domain knowledge and best practices -- **[agents/coding-standards.md](agents/coding-standards.md)** - Coding standards with examples +**Objective:** Ensure consistency and discoverability by requiring repository classes to use 'PrismaRepository' pattern and service classes to use 'Service' pattern, with filenames matching class names exactly in PascalCase + +**Success Criteria:** Repository files are named 'PrismaRepository.ts' with matching exported class names (e.g., PrismaAppRepository), and service files are named 'Service.ts' with matching class names (e.g., MembershipService) + +**Failure Criteria:** Repository or service files use generic names like 'app.ts', use dot-suffixes like '.service.ts' or '.repository.ts', or have filename/class name mismatches + +--- + +## 2. Prevent Circular Dependencies Between Core Packages + +**Objective:** Maintain clear architectural boundaries and prevent circular dependencies by enforcing import restrictions between core packages (lib, app-store, features, trpc) + +**Success Criteria:** The lib package does not import from app-store, features, or trpc; app-store does not import from features or trpc; features does not import from trpc; and trpc does not import from apps/web + +**Failure Criteria:** Code contains imports that violate the dependency hierarchy, such as lib importing from features, app-store importing from trpc, or any other restricted cross-package imports + +--- + +## 3. Use Biome for Code Formatting with Standardized Configuration + +**Objective:** Ensure consistent code formatting across the entire codebase by using Biome with specific formatting rules for line width, indentation, quotes, and semicolons + +**Success Criteria:** All TypeScript/JavaScript files use 110 character line width, 2-space indentation, LF line endings, double quotes for JSX, always include semicolons, use ES5 trailing commas, and always use arrow function parentheses + +**Failure Criteria:** Code files deviate from the standard formatting rules, such as using single quotes in JSX, omitting semicolons, using different indentation widths, or exceeding line width limits + +--- + +## 4. Default Exports Allowed Only in Next.js Page and Layout Files + +**Objective:** Enforce named exports throughout the codebase for better refactoring and tree-shaking, while allowing default exports only where Next.js requires them (page.tsx and layout.tsx files) + +**Success Criteria:** Files use named exports (export const, export function, export class) except for files matching patterns 'apps/web/app/**/page.tsx', 'apps/web/app/**/layout.tsx', and 'apps/web/app/pages/**/*.tsx' which may use default exports + +**Failure Criteria:** Non-page/layout files use default exports, or page/layout files fail to export the required default component + +--- + +## 5. Schema and Handler Files Must Be Separated with Type-Safe Patterns + +**Objective:** Maintain separation of concerns and type safety by requiring schema definitions in separate '.schema.ts' files with both Zod schema and TypeScript type exports, while handlers in '.handler.ts' files use these typed schemas + +**Success Criteria:** Schema files export both a TypeScript type (TInputSchema) and a corresponding Zod schema (ZInputSchema: z.ZodTypeInputSchema>), and handler files import and use these typed schemas for validation + +**Failure Criteria:** Schema and handler logic are mixed in the same file, schema files lack either TypeScript types or Zod schemas, or handler files perform validation without using the defined schemas + +--- + +## 6. Lint Staged Files Before Commit with Error-on-Warnings Enforcement + +**Objective:** Ensure code quality by running Biome linting on staged files before commits and treating warnings as errors unless explicitly skipped via SKIP_WARNINGS environment variable + +**Success Criteria:** Pre-commit hook runs 'biome lint --error-on-warnings' on staged TypeScript/JavaScript files, 'biome format' on JSON files, and 'prisma format' on schema.prisma, and all checks pass before commit is allowed + +**Failure Criteria:** Commits are made with linting warnings or formatting issues, staged files are not checked before commit, or the pre-commit hook is bypassed without proper justification + +--- + +## 7. Environment Variables Must Not Be Accessed Directly in Non-Configuration Code + +**Objective:** Prevent runtime errors and improve testability by avoiding direct process.env access in business logic and instead using centralized configuration modules or environment-specific checks + +**Success Criteria:** Direct process.env access is limited to configuration files, environment detection utilities (isENVProd, isENVDev), and build-time configuration, while business logic receives environment values through dependency injection or configuration objects + +**Failure Criteria:** Business logic, handlers, or service classes directly access process.env properties instead of using configuration abstractions or injected values + +--- + +## 8. All Tests Must Use Vitest Framework and UTC Timezone + +**Objective:** Ensure consistent test execution and prevent timezone-related bugs by standardizing on Vitest as the test framework and enforcing UTC timezone for all test runs + +**Success Criteria:** Test files use Vitest syntax (vi.mock, vi.fn, describe, it, expect), test commands set TZ=UTC environment variable, and tests do not depend on local timezone settings + +**Failure Criteria:** Tests use Jest-specific APIs, test commands omit TZ=UTC setting, or tests fail when run in different timezones + +--- + +## 9. React Components Must Use react-hook-form with Zod Schema Validation + +**Objective:** Ensure consistent form handling and validation by requiring React Hook Form with Zod resolver for all form components, providing type-safe validation and error handling + +**Success Criteria:** Form components use useForm hook with zodResolver, define Zod schemas for form validation, use Controller or register for form fields, and properly handle validation errors with error messages + +**Failure Criteria:** Form components implement custom validation logic without react-hook-form, lack Zod schema validation, or fail to properly display validation errors to users + +--- + +## 10. Custom Error Classes Must Use Hierarchical Structure with Typed Codes + +**Objective:** Enable robust error handling and debugging by requiring custom error classes that extend base Error classes with typed error codes, HTTP status codes, and structured error information + +**Success Criteria:** Error classes extend from base error types (HttpError, CalendarAppError, ErrorWithCode), include typed error codes for categorization, provide statusCode for HTTP errors, and include relevant context (URL, method, cause) + +**Failure Criteria:** Code throws generic Error objects, lacks error categorization, omits HTTP status codes for API errors, or fails to include sufficient debugging context + +--- diff --git a/apps/api/v2/src/ee/bookings/2024-08-13/controllers/booking-location.controller.ts b/apps/api/v2/src/ee/bookings/2024-08-13/controllers/booking-location.controller.ts index 34a08066ac48be..629402a7172f29 100644 --- a/apps/api/v2/src/ee/bookings/2024-08-13/controllers/booking-location.controller.ts +++ b/apps/api/v2/src/ee/bookings/2024-08-13/controllers/booking-location.controller.ts @@ -9,10 +9,18 @@ import { ApiAuthGuard } from "@/modules/auth/guards/api-auth/api-auth.guard"; import { PermissionsGuard } from "@/modules/auth/guards/permissions/permissions.guard"; import { ApiAuthGuardUser } from "@/modules/auth/strategies/api-auth/api-auth.strategy"; import { Controller, Patch, Logger, Body, UseGuards, Param, HttpCode, HttpStatus } from "@nestjs/common"; -import { ApiOperation, ApiTags as DocsTags, ApiHeader } from "@nestjs/swagger"; +import { ApiExtraModels, ApiOperation, ApiTags as DocsTags, ApiHeader } from "@nestjs/swagger"; import { BOOKING_WRITE, SUCCESS_STATUS } from "@calcom/platform-constants"; -import { UpdateBookingLocationInput_2024_08_13 } from "@calcom/platform-types"; +import { + UpdateBookingLocationInput_2024_08_13, + UpdateInputAddressLocation_2024_08_13, + UpdateBookingInputAttendeeAddressLocation_2024_08_13, + UpdateBookingInputAttendeeDefinedLocation_2024_08_13, + UpdateBookingInputAttendeePhoneLocation_2024_08_13, + UpdateBookingInputLinkLocation_2024_08_13, + UpdateBookingInputPhoneLocation_2024_08_13, +} from "@calcom/platform-types"; @Controller({ path: "/v2/bookings/:bookingUid/location", @@ -20,6 +28,14 @@ import { UpdateBookingLocationInput_2024_08_13 } from "@calcom/platform-types"; }) @UseGuards(PermissionsGuard) @DocsTags("Bookings") +@ApiExtraModels( + UpdateInputAddressLocation_2024_08_13, + UpdateBookingInputAttendeeAddressLocation_2024_08_13, + UpdateBookingInputAttendeeDefinedLocation_2024_08_13, + UpdateBookingInputAttendeePhoneLocation_2024_08_13, + UpdateBookingInputLinkLocation_2024_08_13, + UpdateBookingInputPhoneLocation_2024_08_13 +) @ApiHeader({ name: "cal-api-version", description: `Must be set to ${VERSION_2024_08_13}. This header is required as this endpoint does not exist in older API versions.`, diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json index 716241f6133498..95451c7002fbf2 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,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -6965,11 +6965,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 +6978,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -7122,11 +7122,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 +7135,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -7665,10 +7665,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 +7677,9 @@ "required": false, "in": "query", "description": "The number of items to skip", - "example": 0, "schema": { "minimum": 0, + "example": 0, "type": "number" } }, @@ -7688,11 +7688,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 +7704,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 +7717,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 +7733,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 +8010,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 +8030,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 +8040,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's name.", - "example": "John Doe", "schema": { + "example": "John Doe", "type": "string" } }, @@ -8050,8 +8050,8 @@ "required": false, "in": "query", "description": "Filter bookings by the booking Uid.", - "example": "2NtaeaVcKfpmSZ4CthFdfk", "schema": { + "example": "2NtaeaVcKfpmSZ4CthFdfk", "type": "string" } }, @@ -8060,8 +8060,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 +8070,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 +8080,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 +8090,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 +8100,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 +8110,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 +8120,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 +8130,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 +8140,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 +8150,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 +8160,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 +8174,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 +8188,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 +8202,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 +8216,9 @@ "required": false, "in": "query", "description": "The number of items to return", - "example": 10, "schema": { "default": 100, + "example": 10, "type": "number" } }, @@ -8227,9 +8227,9 @@ "required": false, "in": "query", "description": "The number of items to skip", - "example": 0, "schema": { "default": 0, + "example": 0, "type": "number" } } @@ -8289,11 +8289,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 +8302,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -8314,8 +8314,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 +8328,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 +8570,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 +8583,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -8595,8 +8595,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 +8609,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 +8623,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 +9012,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 +9025,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -9440,8 +9440,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 +9460,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 +9470,8 @@ "required": false, "in": "query", "description": "Filter bookings by the attendee's name.", - "example": "John Doe", "schema": { + "example": "John Doe", "type": "string" } }, @@ -9480,8 +9480,8 @@ "required": false, "in": "query", "description": "Filter bookings by the booking Uid.", - "example": "2NtaeaVcKfpmSZ4CthFdfk", "schema": { + "example": "2NtaeaVcKfpmSZ4CthFdfk", "type": "string" } }, @@ -9490,8 +9490,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 +9500,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 +9510,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 +9520,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 +9530,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 +9540,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 +9550,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 +9560,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 +9570,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 +9580,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 +9590,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 +9604,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 +9618,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 +9632,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 +9646,9 @@ "required": false, "in": "query", "description": "The number of items to return", - "example": 10, "schema": { "default": 100, + "example": 10, "type": "number" } }, @@ -9657,9 +9657,9 @@ "required": false, "in": "query", "description": "The number of items to skip", - "example": 0, "schema": { "default": 0, + "example": 0, "type": "number" } }, @@ -10408,8 +10408,8 @@ "required": false, "in": "query", "description": "Filter booking references by type", - "example": "google_calendar", "schema": { + "example": "google_calendar", "enum": [ "google_calendar", "office365_calendar", @@ -10820,8 +10820,8 @@ "required": true, "in": "query", "description": "The timezone of the logged in user represented as a string", - "example": "America/New_York", "schema": { + "example": "America/New_York", "type": "string" } }, @@ -10830,8 +10830,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 +10840,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" } }, @@ -11505,8 +11505,8 @@ "required": false, "in": "query", "description": "The number of items to return", - "example": 10, "schema": { + "example": 10, "type": "number" } }, @@ -11515,8 +11515,8 @@ "required": false, "in": "query", "description": "The number of items to skip", - "example": 0, "schema": { + "example": 0, "type": "number" } }, @@ -11525,8 +11525,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" @@ -11924,11 +11924,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" } }, @@ -11937,10 +11937,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -12754,11 +12754,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" } }, @@ -12767,10 +12767,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -13227,11 +13227,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" } }, @@ -13240,10 +13240,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -13251,9 +13251,9 @@ "name": "slug", "required": false, "in": "query", - "example": "organization-slug", "description": "The slug of the managed organization", "schema": { + "example": "organization-slug", "type": "string" } }, @@ -13261,9 +13261,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" } }, @@ -13271,9 +13271,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" } } @@ -13738,11 +13738,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" } }, @@ -13751,10 +13751,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -13803,11 +13803,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" } }, @@ -13816,10 +13816,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -13966,8 +13966,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" } }, @@ -13976,8 +13976,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" } }, @@ -13986,8 +13986,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" } }, @@ -13996,8 +13996,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" } }, @@ -14006,8 +14006,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" @@ -14020,8 +14020,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" } }, @@ -14472,96 +14472,108 @@ "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": {} + "schema": { + "example": "abc123def456" + } }, { "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.", - "example": "2050-09-05", - "schema": {} + "schema": { + "example": "2050-09-05" + } }, { "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.", - "example": "2050-09-06", - "schema": {} + "schema": { + "example": "2050-09-06" + } }, { "name": "organizationSlug", "required": false, "in": "query", "description": "The slug of the organization to which user with username belongs or team with teamSlug belongs.", - "example": "org-slug", - "schema": {} + "schema": { + "example": "org-slug" + } }, { "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.", - "example": "team-slug", - "schema": {} + "schema": { + "example": "team-slug" + } }, { "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.", - "example": "bob", - "schema": {} + "schema": { + "example": "bob" + } }, { "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.", - "example": "event-type-slug", - "schema": {} + "schema": { + "example": "event-type-slug" + } }, { "name": "eventTypeId", "required": false, "in": "query", "description": "The ID of the event type for which available slots should be checked.", - "example": "100", - "schema": {} + "schema": { + "example": "100" + } }, { "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.", - "example": "alice,bob", - "schema": {} + "schema": { + "example": "alice,bob" + } }, { "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.", - "example": "range", - "schema": {} + "schema": { + "example": "range" + } }, { "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.", - "example": "60", - "schema": {} + "schema": { + "example": "60" + } }, { "name": "timeZone", "required": false, "in": "query", "description": "Time zone in which the available slots should be returned. Defaults to UTC.", - "example": "Europe/Rome", - "schema": {} + "schema": { + "example": "Europe/Rome" + } } ], "responses": { @@ -15548,11 +15560,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" } }, @@ -15561,10 +15573,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -15810,11 +15822,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" } }, @@ -15823,10 +15835,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -15835,8 +15847,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" @@ -16038,11 +16050,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" } }, @@ -16051,10 +16063,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -16282,11 +16294,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" } }, @@ -16295,10 +16307,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -16347,11 +16359,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" } }, @@ -16360,10 +16372,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -16672,11 +16684,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" } }, @@ -16685,10 +16697,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -16729,11 +16741,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" } }, @@ -16742,10 +16754,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } }, @@ -16916,11 +16928,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" } }, @@ -16929,10 +16941,10 @@ "required": false, "in": "query", "description": "Number of items to skip", - "example": 0, "schema": { "minimum": 0, "default": 0, + "example": 0, "type": "number" } } @@ -33806,6 +33818,114 @@ "data" ] }, + "UpdateInputAddressLocation_2024_08_13": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "address", + "description": "only allowed value for type is `address` - it refers to address defined by the organizer." + }, + "address": { + "type": "string", + "example": "123 Example St, City, Country" + } + }, + "required": [ + "type", + "address" + ] + }, + "UpdateBookingInputAttendeeAddressLocation_2024_08_13": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "attendeeAddress", + "description": "only allowed value for type is `attendeeAddress`" + }, + "address": { + "type": "string", + "example": "123 Example St, City, Country" + } + }, + "required": [ + "type", + "address" + ] + }, + "UpdateBookingInputAttendeeDefinedLocation_2024_08_13": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "attendeeDefined", + "description": "only allowed value for type is `attendeeDefined`" + }, + "location": { + "type": "string", + "example": "321 Example St, City, Country" + } + }, + "required": [ + "type", + "location" + ] + }, + "UpdateBookingInputAttendeePhoneLocation_2024_08_13": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "attendeePhone", + "description": "only allowed value for type is `attendeePhone`" + }, + "phone": { + "type": "string", + "example": "+37120993151" + } + }, + "required": [ + "type", + "phone" + ] + }, + "UpdateBookingInputLinkLocation_2024_08_13": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "link", + "description": "only allowed value for type is `link` - it refers to link defined by the organizer." + }, + "link": { + "type": "string", + "example": "https://meet.google.com/txi-fein-xyz" + } + }, + "required": [ + "type", + "link" + ] + }, + "UpdateBookingInputPhoneLocation_2024_08_13": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "phone", + "description": "only allowed value for type is `phone` - it refers to phone defined by the organizer." + }, + "phone": { + "type": "string", + "example": "+37120993151" + } + }, + "required": [ + "type", + "phone" + ] + }, "UpdateBookingLocationInput_2024_08_13": { "type": "object", "properties": { diff --git a/packages/features/ee/billing/service/proration/MonthlyProrationService.ts b/packages/features/ee/billing/service/proration/MonthlyProrationService.ts index a987e7c973508f..db93f20abc134d 100644 --- a/packages/features/ee/billing/service/proration/MonthlyProrationService.ts +++ b/packages/features/ee/billing/service/proration/MonthlyProrationService.ts @@ -9,7 +9,7 @@ import type { IBillingProviderService } from "../billingProvider/IBillingProvide import { StripeBillingService } from "../billingProvider/StripeBillingService"; import { SeatChangeTrackingService } from "../seatTracking/SeatChangeTrackingService"; -const log = logger.getSubLogger({ prefix: ["MonthlyProrationService"] }); +const log = logger.getSubLogger({ prefix: ["ProrationService"] }); interface ProrationCalculation { proratedAmount: number; @@ -30,7 +30,7 @@ export interface MonthlyProrationServiceDeps { logger: ISimpleLogger; } -export class MonthlyProrationService { +export class ProrationService { private logger: ISimpleLogger; private teamRepository: MonthlyProrationTeamRepository; private prorationRepository: MonthlyProrationRepository; diff --git a/packages/platform/types/bookings/2024-08-13/inputs/update-location.input.ts b/packages/platform/types/bookings/2024-08-13/inputs/update-location.input.ts index e3c5b284df44f8..368c2eedc6629a 100644 --- a/packages/platform/types/bookings/2024-08-13/inputs/update-location.input.ts +++ b/packages/platform/types/bookings/2024-08-13/inputs/update-location.input.ts @@ -1,4 +1,4 @@ -import { ApiPropertyOptional, getSchemaPath } from "@nestjs/swagger"; +import { ApiExtraModels, ApiPropertyOptional, getSchemaPath } from "@nestjs/swagger"; import { ApiProperty as DocsProperty } from "@nestjs/swagger"; import { plainToInstance } from "class-transformer"; import { IsOptional } from "class-validator"; @@ -109,6 +109,14 @@ export function ValidateUpdateBookingLocation_2024_08_13(validationOptions?: Val }; } +@ApiExtraModels( + UpdateInputAddressLocation_2024_08_13, + UpdateBookingInputAttendeeAddressLocation_2024_08_13, + UpdateBookingInputAttendeeDefinedLocation_2024_08_13, + UpdateBookingInputAttendeePhoneLocation_2024_08_13, + UpdateBookingInputLinkLocation_2024_08_13, + UpdateBookingInputPhoneLocation_2024_08_13 +) export class UpdateBookingLocationInput_2024_08_13 { @IsOptional() @ValidateUpdateBookingLocation_2024_08_13()