From 74b4d7a94a27a6a99d58b11307b72f997c7446ce Mon Sep 17 00:00:00 2001 From: Keith Williams Date: Wed, 13 Nov 2024 12:28:25 -0300 Subject: [PATCH] chore: Automated API v2 OpenAPI spec generation (#17046) * chore: Automated API v2 OpenAPI spec generation * chore: update docs --------- Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com> Co-authored-by: Morgan Vernay --- apps/api/v2/src/main.ts | 16 +- .../oauth-flow/oauth-flow.controller.ts | 32 +- .../controllers/webhooks.controller.ts | 5 +- apps/api/v2/swagger/documentation.json | 220 ++- docs/api-reference/v2/openapi.json | 1393 +++++++++++++---- 5 files changed, 1201 insertions(+), 465 deletions(-) diff --git a/apps/api/v2/src/main.ts b/apps/api/v2/src/main.ts index 8202d06592..b16f360d92 100644 --- a/apps/api/v2/src/main.ts +++ b/apps/api/v2/src/main.ts @@ -1,4 +1,5 @@ import type { AppConfig } from "@/config/type"; +import { getEnv } from "@/env"; import { Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { NestFactory } from "@nestjs/core"; @@ -107,13 +108,20 @@ async function generateSwagger(app: NestExpressApplication) { const document = SwaggerModule.createDocument(app, config); document.paths = groupAndSortPathsByFirstTag(document.paths); - const outputFile = "./swagger/documentation.json"; + const swaggerOutputFile = "./swagger/documentation.json"; + const docsOutputFile = "../../../docs/api-reference/v2/openapi.json"; + const stringifiedContents = JSON.stringify(document, null, 2); - if (fs.existsSync(outputFile)) { - fs.unlinkSync(outputFile); + if (fs.existsSync(swaggerOutputFile)) { + fs.unlinkSync(swaggerOutputFile); } - fs.writeFileSync(outputFile, JSON.stringify(document, null, 2), { encoding: "utf8" }); + fs.writeFileSync(swaggerOutputFile, stringifiedContents, { encoding: "utf8" }); + + if (fs.existsSync(docsOutputFile) && getEnv("NODE_ENV") === "development") { + fs.unlinkSync(docsOutputFile); + fs.writeFileSync(docsOutputFile, stringifiedContents, { encoding: "utf8" }); + } if (!process.env.DOCS_URL) { SwaggerModule.setup("docs", app, document, { diff --git a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-flow/oauth-flow.controller.ts b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-flow/oauth-flow.controller.ts index 02af38d795..8e77d625df 100644 --- a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-flow/oauth-flow.controller.ts +++ b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-flow/oauth-flow.controller.ts @@ -25,9 +25,9 @@ import { import { ApiTags as DocsTags, ApiExcludeController as DocsExcludeController, - ApiExcludeEndpoint as DocsExcludeEndpoint, ApiOperation as DocsOperation, ApiOkResponse as DocsOkResponse, + ApiExcludeEndpoint as DocsExcludeEndpoint, ApiBadRequestResponse as DocsBadRequestResponse, ApiHeader as DocsHeader, } from "@nestjs/swagger"; @@ -50,20 +50,7 @@ export class OAuthFlowController { @Post("/authorize") @HttpCode(HttpStatus.OK) @UseGuards(NextAuthGuard) - @DocsOperation({ - summary: "Authorize an OAuth client", - description: - "Redirects the user to the specified 'redirect_uri' with an authorization code in query parameter if the client is authorized successfully. The code is then exchanged for access and refresh tokens via the `/exchange` endpoint.", - }) - @DocsOkResponse({ - description: - "The user is redirected to the 'redirect_uri' with an authorization code in query parameter e.g. `redirectUri?code=secretcode.`", - }) - @DocsBadRequestResponse({ - description: - "Bad request if the OAuth client is not found, if the redirect URI is invalid, or if the user has already authorized the client.", - }) - @DocsExcludeEndpoint(getEnv("NODE_ENV") === "production") + @DocsExcludeEndpoint() async authorize( @Param("clientId") clientId: string, @Body() body: OAuthAuthorizeInput, @@ -97,20 +84,7 @@ export class OAuthFlowController { @Post("/exchange") @HttpCode(HttpStatus.OK) - @DocsOperation({ - summary: "Exchange authorization code for access tokens", - description: - "Exchanges the authorization code received from the `/authorize` endpoint for access and refresh tokens. The authorization code should be provided in the 'Authorization' header prefixed with 'Bearer '.", - }) - @DocsOkResponse({ - type: KeysResponseDto, - description: "Successfully exchanged authorization code for access and refresh tokens.", - }) - @DocsBadRequestResponse({ - description: - "Bad request if the authorization code is missing, invalid, or if the client ID and secret do not match.", - }) - @DocsExcludeEndpoint(getEnv("NODE_ENV") === "production") + @DocsExcludeEndpoint() async exchange( @Headers("Authorization") authorization: string, @Param("clientId") clientId: string, diff --git a/apps/api/v2/src/modules/webhooks/controllers/webhooks.controller.ts b/apps/api/v2/src/modules/webhooks/controllers/webhooks.controller.ts index 01daf79673..5025699ddd 100644 --- a/apps/api/v2/src/modules/webhooks/controllers/webhooks.controller.ts +++ b/apps/api/v2/src/modules/webhooks/controllers/webhooks.controller.ts @@ -82,7 +82,10 @@ export class WebhooksController { } @Get("/") - @ApiOperation({ summary: "Get all webooks (paginated)" }) + @ApiOperation({ + summary: "Get all webooks", + description: "Gets a paginated list of webhooks for the authenticated user.", + }) async getWebhooks( @GetUser() user: UserWithProfile, @Query() query: SkipTakePagination diff --git a/apps/api/v2/swagger/documentation.json b/apps/api/v2/swagger/documentation.json index b160d360d3..ff15248b72 100644 --- a/apps/api/v2/swagger/documentation.json +++ b/apps/api/v2/swagger/documentation.json @@ -4438,97 +4438,6 @@ ] } }, - "/v2/oauth/{clientId}/authorize": { - "post": { - "operationId": "OAuthFlowController_authorize", - "summary": "Authorize an OAuth client", - "description": "Redirects the user to the specified 'redirect_uri' with an authorization code in query parameter if the client is authorized successfully. The code is then exchanged for access and refresh tokens via the `/exchange` endpoint.", - "parameters": [ - { - "name": "clientId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OAuthAuthorizeInput" - } - } - } - }, - "responses": { - "200": { - "description": "The user is redirected to the 'redirect_uri' with an authorization code in query parameter e.g. `redirectUri?code=secretcode.`" - }, - "400": { - "description": "Bad request if the OAuth client is not found, if the redirect URI is invalid, or if the user has already authorized the client." - } - }, - "tags": [ - "OAuth" - ] - } - }, - "/v2/oauth/{clientId}/exchange": { - "post": { - "operationId": "OAuthFlowController_exchange", - "summary": "Exchange authorization code for access tokens", - "description": "Exchanges the authorization code received from the `/authorize` endpoint for access and refresh tokens. The authorization code should be provided in the 'Authorization' header prefixed with 'Bearer '.", - "parameters": [ - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } - }, - { - "name": "clientId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExchangeAuthorizationCodeInput" - } - } - } - }, - "responses": { - "200": { - "description": "Successfully exchanged authorization code for access and refresh tokens.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/KeysResponseDto" - } - } - } - }, - "400": { - "description": "Bad request if the authorization code is missing, invalid, or if the client ID and secret do not match." - } - }, - "tags": [ - "OAuth" - ] - } - }, "/v2/oauth/{clientId}/refresh": { "post": { "operationId": "OAuthFlowController_refreshAccessToken", @@ -5343,7 +5252,8 @@ }, "get": { "operationId": "WebhooksController_getWebhooks", - "summary": "Get all webooks (paginated)", + "summary": "Get all webooks", + "description": "Gets a paginated list of webhooks for the authenticated user.", "parameters": [ { "name": "take", @@ -6073,28 +5983,6 @@ } } }, - "OAuthAuthorizeInput": { - "type": "object", - "properties": { - "redirectUri": { - "type": "string" - } - }, - "required": [ - "redirectUri" - ] - }, - "ExchangeAuthorizationCodeInput": { - "type": "object", - "properties": { - "clientSecret": { - "type": "string" - } - }, - "required": [ - "clientSecret" - ] - }, "RefreshTokenInput": { "type": "object", "properties": { @@ -6975,6 +6863,18 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [ + 15, + 30, + 60 + ], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -7198,6 +7098,7 @@ }, "required": [ "lengthInMinutes", + "lengthInMinutesOptions", "title", "slug" ] @@ -8340,6 +8241,18 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [ + 15, + 30, + 60 + ], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -8563,6 +8476,7 @@ "required": [ "id", "lengthInMinutes", + "lengthInMinutesOptions", "title", "slug", "description", @@ -8678,6 +8592,18 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [ + 15, + 30, + 60 + ], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -8898,7 +8824,10 @@ "hideCalendarEventDetails": { "type": "boolean" } - } + }, + "required": [ + "lengthInMinutesOptions" + ] }, "UpdateEventTypeOutput_2024_06_14": { "type": "object", @@ -10157,6 +10086,18 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [ + 15, + 30, + 60 + ], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -10393,6 +10334,7 @@ }, "required": [ "lengthInMinutes", + "lengthInMinutesOptions", "title", "slug", "schedulingType", @@ -10474,6 +10416,19 @@ "minimum": 1, "example": 60 }, + "lengthInMinutesOptions": { + "example": [ + 15, + 30, + 60 + ], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "number", + "minimum": 1 + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -10899,6 +10854,18 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [ + 15, + 30, + 60 + ], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -11129,7 +11096,10 @@ "type": "boolean", "description": "If true, all current and future team members will be assigned to this event type" } - } + }, + "required": [ + "lengthInMinutesOptions" + ] }, "UpdateTeamEventTypeOutput": { "type": "object", @@ -12839,6 +12809,11 @@ "description": "The start time of the booking in ISO 8601 format in UTC timezone.", "example": "2024-08-13T09:00:00Z" }, + "lengthInMinutes": { + "type": "number", + "example": 30, + "description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking." + }, "eventTypeId": { "type": "number", "description": "The ID of the event type that is booked.", @@ -12884,6 +12859,7 @@ }, "required": [ "start", + "lengthInMinutes", "eventTypeId", "attendee" ] @@ -12896,6 +12872,11 @@ "description": "The start time of the booking in ISO 8601 format in UTC timezone.", "example": "2024-08-13T09:00:00Z" }, + "lengthInMinutes": { + "type": "number", + "example": 30, + "description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking." + }, "eventTypeId": { "type": "number", "description": "The ID of the event type that is booked.", @@ -12946,6 +12927,7 @@ }, "required": [ "start", + "lengthInMinutes", "eventTypeId", "attendee", "instant" @@ -12959,6 +12941,11 @@ "description": "The start time of the booking in ISO 8601 format in UTC timezone.", "example": "2024-08-13T09:00:00Z" }, + "lengthInMinutes": { + "type": "number", + "example": 30, + "description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking." + }, "eventTypeId": { "type": "number", "description": "The ID of the event type that is booked.", @@ -13009,6 +12996,7 @@ }, "required": [ "start", + "lengthInMinutes", "eventTypeId", "attendee" ] diff --git a/docs/api-reference/v2/openapi.json b/docs/api-reference/v2/openapi.json index 9d038ce06b..73f17646d8 100644 --- a/docs/api-reference/v2/openapi.json +++ b/docs/api-reference/v2/openapi.json @@ -1901,7 +1901,7 @@ "/v2/organizations/{orgId}/teams/me": { "get": { "operationId": "OrganizationsTeamsController_getMyTeams", - "summary": "Get team membership for user", + "summary": "Get teams membership for user", "parameters": [ { "name": "orgId", @@ -2290,6 +2290,35 @@ "tags": ["Orgs / Teams / Memberships"] } }, + "/v2/organizations/{orgId}/teams/{teamId}/users/{userId}/schedules": { + "get": { + "operationId": "OrganizationsTeamsSchedulesController_getUserSchedules", + "summary": "Get schedules of a team member", + "parameters": [ + { + "name": "userId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetSchedulesOutput_2024_06_11" + } + } + } + } + }, + "tags": ["Orgs / Teams / Schedules", "Orgs / Teams / Users / Schedules"] + } + }, "/v2/organizations/{orgId}/users": { "get": { "operationId": "OrganizationsUsersController_getOrganizationsUsers", @@ -2834,7 +2863,7 @@ "required": false, "in": "query", "description": "Sort results by their creation time (when booking was made) in ascending or descending order.", - "example": "?sortEnd=asc OR ?sortEnd=desc", + "example": "?sortCreated=asc OR ?sortCreated=desc", "schema": { "enum": ["asc", "desc"], "type": "string" @@ -2948,16 +2977,6 @@ } } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RescheduleBookingInput_2024_08_13" - } - } - } - }, "responses": { "201": { "description": "", @@ -2996,16 +3015,6 @@ } } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CancelBookingInput_2024_08_13" - } - } - } - }, "responses": { "200": { "description": "", @@ -3078,6 +3087,222 @@ "tags": ["Bookings"] } }, + "/v2/bookings/{bookingUid}/reassign": { + "post": { + "operationId": "BookingsController_2024_08_13_reassignBooking", + "summary": "Automatically reassign booking to a new host", + "parameters": [ + { + "name": "cal-api-version", + "in": "header", + "description": "Must be set to `2024-08-13`", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "bookingUid", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "value must be `Bearer ` where `` either managed user access token or api key prefixed with cal_", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReassignBookingOutput_2024_08_13" + } + } + } + } + }, + "tags": ["Bookings"] + } + }, + "/v2/bookings/{bookingUid}/reassign/{userId}": { + "post": { + "operationId": "BookingsController_2024_08_13_reassignBookingToUser", + "summary": "Reassign a booking to a specific user", + "parameters": [ + { + "name": "cal-api-version", + "in": "header", + "description": "Must be set to `2024-08-13`", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "bookingUid", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "userId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "value must be `Bearer ` where `` either managed user access token or api key prefixed with cal_", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReassignToUserBookingInput_2024_08_13" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReassignBookingOutput_2024_08_13" + } + } + } + } + }, + "tags": ["Bookings"] + } + }, + "/v2/bookings/{bookingUid}/confirm": { + "post": { + "operationId": "BookingsController_2024_08_13_confirmBooking", + "summary": "Confirm booking that requires a confirmation", + "parameters": [ + { + "name": "cal-api-version", + "in": "header", + "description": "Must be set to `2024-08-13`", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "bookingUid", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "value must be `Bearer ` where `` either managed user access token or api key prefixed with cal_", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBookingOutput_2024_08_13" + } + } + } + } + }, + "tags": ["Bookings"] + } + }, + "/v2/bookings/{bookingUid}/decline": { + "post": { + "operationId": "BookingsController_2024_08_13_declineBooking", + "summary": "Decline booking that requires a confirmation", + "parameters": [ + { + "name": "cal-api-version", + "in": "header", + "description": "Must be set to `2024-08-13`", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "bookingUid", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "Authorization", + "in": "header", + "description": "value must be `Bearer ` where `` either managed user access token or api key prefixed with cal_", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeclineBookingInput_2024_08_13" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetBookingOutput_2024_08_13" + } + } + } + } + }, + "tags": ["Bookings"] + } + }, "/v2/calendars/ics-feed/save": { "post": { "operationId": "CalendarsController_createIcsFeed", @@ -3981,93 +4206,6 @@ "tags": ["Me"] } }, - "/v2/oauth/{clientId}/authorize": { - "post": { - "operationId": "OAuthFlowController_authorize", - "summary": "Authorize an OAuth client", - "description": "Redirects the user to the specified 'redirect_uri' with an authorization code in query parameter if the client is authorized successfully. The code is then exchanged for access and refresh tokens via the `/exchange` endpoint.", - "parameters": [ - { - "name": "clientId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OAuthAuthorizeInput" - } - } - } - }, - "responses": { - "200": { - "description": "The user is redirected to the 'redirect_uri' with an authorization code in query parameter e.g. `redirectUri?code=secretcode.`" - }, - "400": { - "description": "Bad request if the OAuth client is not found, if the redirect URI is invalid, or if the user has already authorized the client." - } - }, - "tags": ["OAuth"] - } - }, - "/v2/oauth/{clientId}/exchange": { - "post": { - "operationId": "OAuthFlowController_exchange", - "summary": "Exchange authorization code for access tokens", - "description": "Exchanges the authorization code received from the `/authorize` endpoint for access and refresh tokens. The authorization code should be provided in the 'Authorization' header prefixed with 'Bearer '.", - "parameters": [ - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } - }, - { - "name": "clientId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExchangeAuthorizationCodeInput" - } - } - } - }, - "responses": { - "200": { - "description": "Successfully exchanged authorization code for access and refresh tokens.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/KeysResponseDto" - } - } - } - }, - "400": { - "description": "Bad request if the authorization code is missing, invalid, or if the client ID and secret do not match." - } - }, - "tags": ["OAuth"] - } - }, "/v2/oauth/{clientId}/refresh": { "post": { "operationId": "OAuthFlowController_refreshAccessToken", @@ -4765,6 +4903,35 @@ "tags": ["Stripe"] } }, + "/v2/stripe/check/{teamId}": { + "get": { + "operationId": "StripeController_checkTeamStripeConnection", + "summary": "Check team stripe connection", + "parameters": [ + { + "name": "teamId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StripCredentialsCheckOutputResponseDto" + } + } + } + } + }, + "tags": ["Stripe"] + } + }, "/v2/timezones": { "get": { "operationId": "TimezonesController_getTimeZones", @@ -4816,7 +4983,8 @@ }, "get": { "operationId": "WebhooksController_getWebhooks", - "summary": "Get all webooks (paginated)", + "summary": "Get all webooks", + "description": "Gets a paginated list of webhooks for the authenticated user.", "parameters": [ { "name": "take", @@ -5096,7 +5264,7 @@ "timeZone": { "type": "string", "example": "America/New_York", - "description": "Timezone is used to create user's default schedule from Monday to Friday from 9AM to 5PM. If it is not passed then user does not have\n a default schedule and it must be created manually via the /schedules endpoint. Until the schedule is created, the user can't access availability atom to set his / her availability nor booked." + "description": "Timezone is used to create user's default schedule from Monday to Friday from 9AM to 5PM. If it is not passed then user does not have\n a default schedule and it must be created manually via the /schedules endpoint. Until the schedule is created, the user can't access availability atom to set his / her availability nor booked.\n It will default to Europe/London if not passed." }, "locale": { "enum": [ @@ -5177,6 +5345,9 @@ }, "data": { "$ref": "#/components/schemas/CreateManagedUserData" + }, + "error": { + "type": "object" } }, "required": ["status", "data"] @@ -5446,24 +5617,6 @@ } } }, - "OAuthAuthorizeInput": { - "type": "object", - "properties": { - "redirectUri": { - "type": "string" - } - }, - "required": ["redirectUri"] - }, - "ExchangeAuthorizationCodeInput": { - "type": "object", - "properties": { - "clientSecret": { - "type": "string" - } - }, - "required": ["clientSecret"] - }, "RefreshTokenInput": { "type": "object", "properties": { @@ -5474,7 +5627,7 @@ }, "required": ["refreshToken"] }, - "AddressLocation_2024_06_14": { + "InputAddressLocation_2024_06_14": { "type": "object", "properties": { "type": { @@ -5492,7 +5645,7 @@ }, "required": ["type", "address", "public"] }, - "LinkLocation_2024_06_14": { + "InputLinkLocation_2024_06_14": { "type": "object", "properties": { "type": { @@ -5510,7 +5663,7 @@ }, "required": ["type", "link", "public"] }, - "IntegrationLocation_2024_06_14": { + "InputIntegrationLocation_2024_06_14": { "type": "object", "properties": { "type": { @@ -5521,12 +5674,12 @@ "integration": { "type": "string", "example": "cal-video", - "enum": ["cal-video"] + "enum": ["cal-video", "google-meet"] } }, "required": ["type", "integration"] }, - "PhoneLocation_2024_06_14": { + "InputPhoneLocation_2024_06_14": { "type": "object", "properties": { "type": { @@ -5565,6 +5718,10 @@ }, "placeholder": { "type": "string" + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `phone` and the URL contains query parameter `&phone=1234567890`, the phone field will be prefilled with this value and disabled." } }, "required": ["type", "slug", "label", "required", "placeholder"] @@ -5592,6 +5749,10 @@ "placeholder": { "type": "string", "example": "e.g., 1234 Main St" + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `address` and the URL contains query parameter `&address=1234 Main St, London`, the address field will be prefilled with this value and disabled." } }, "required": ["type", "slug", "label", "required", "placeholder"] @@ -5619,6 +5780,10 @@ "placeholder": { "type": "string", "example": "e.g., Enter text here" + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `who-referred-you` and the URL contains query parameter `&who-referred-you=bob`, the text field will be prefilled with this value and disabled." } }, "required": ["type", "slug", "label", "required", "placeholder"] @@ -5646,6 +5811,10 @@ "placeholder": { "type": "string", "example": "e.g., 100" + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `calories-per-day` and the URL contains query parameter `&calories-per-day=3000`, the number field will be prefilled with this value and disabled." } }, "required": ["type", "slug", "label", "required", "placeholder"] @@ -5673,6 +5842,10 @@ "placeholder": { "type": "string", "example": "e.g., Detailed description here..." + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `dear-diary` and the URL contains query parameter `&dear-diary=Today I shipped a feature`, the text area will be prefilled with this value and disabled." } }, "required": ["type", "slug", "label", "required", "placeholder"] @@ -5707,6 +5880,10 @@ "items": { "type": "string" } + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `language` and options of this select field are ['english', 'italian'] and the URL contains query parameter `&language=italian`, the 'italian' will be selected and the select field will be disabled." } }, "required": ["type", "slug", "label", "required", "placeholder", "options"] @@ -5737,6 +5914,10 @@ "items": { "type": "string" } + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `consultants` and the URL contains query parameter `&consultants=en&language=it`, the 'en' and 'it' will be selected and the select field will be disabled." } }, "required": ["type", "slug", "label", "required", "options"] @@ -5764,6 +5945,10 @@ "placeholder": { "type": "string", "example": "e.g., example@example.com" + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `consultants` and the URL contains query parameter `&consultants=alice@gmail.com&consultants=bob@gmail.com`, the these emails will be added and none more can be added." } }, "required": ["type", "slug", "label", "required", "placeholder"] @@ -5794,6 +5979,10 @@ "items": { "type": "string" } + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `notify-me` and the URL contains query parameter `¬ify-me=true`, the checkbox will be selected and the checkbox field will be disabled." } }, "required": ["type", "slug", "label", "required", "options"] @@ -5824,6 +6013,10 @@ "items": { "type": "string" } + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `language` and options of this select field are ['english', 'italian'] and the URL contains query parameter `&language=italian`, the 'italian' radio buttom will be selected and the select field will be disabled." } }, "required": ["type", "slug", "label", "required", "options"] @@ -5847,6 +6040,9 @@ }, "required": { "type": "boolean" + }, + "disableOnPrefill": { + "type": "boolean" } }, "required": ["type", "slug", "label", "required"] @@ -6050,6 +6246,39 @@ }, "required": ["seatsPerTimeSlot", "showAttendeeInfo", "showAvailabilityCount"] }, + "InputAttendeeAddressLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "attendeeAddress", + "description": "only allowed value for type is `attendeeAddress`" + } + }, + "required": ["type"] + }, + "InputAttendeePhoneLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "attendeePhone", + "description": "only allowed value for type is `attendeePhone`" + } + }, + "required": ["type"] + }, + "InputAttendeeDefinedLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "example": "attendeeDefined", + "description": "only allowed value for type is `attendeeDefined`" + } + }, + "required": ["type"] + }, "BookerLayouts_2024_06_14": { "type": "object", "properties": { @@ -6104,6 +6333,14 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [15, 30, 60], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -6122,16 +6359,25 @@ "items": { "oneOf": [ { - "$ref": "#/components/schemas/AddressLocation_2024_06_14" + "$ref": "#/components/schemas/InputAddressLocation_2024_06_14" }, { - "$ref": "#/components/schemas/LinkLocation_2024_06_14" + "$ref": "#/components/schemas/InputLinkLocation_2024_06_14" }, { - "$ref": "#/components/schemas/IntegrationLocation_2024_06_14" + "$ref": "#/components/schemas/InputIntegrationLocation_2024_06_14" }, { - "$ref": "#/components/schemas/PhoneLocation_2024_06_14" + "$ref": "#/components/schemas/InputPhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeeAddressLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeePhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeeDefinedLocation_2024_06_14" } ] } @@ -6316,11 +6562,235 @@ "type": "boolean" } }, - "required": ["lengthInMinutes", "title", "slug"] + "required": ["lengthInMinutes", "lengthInMinutesOptions", "title", "slug"] + }, + "OutputAddressLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "address", + "link", + "integration", + "phone", + "attendeeAddress", + "attendeePhone", + "attendeeDefined" + ], + "example": "address", + "description": "only allowed value for type is `address`" + }, + "address": { + "type": "string", + "example": "123 Example St, City, Country" + }, + "public": { + "type": "boolean" + } + }, + "required": ["type", "address", "public"] + }, + "OutputLinkLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "address", + "link", + "integration", + "phone", + "attendeeAddress", + "attendeePhone", + "attendeeDefined" + ], + "example": "link", + "description": "only allowed value for type is `link`" + }, + "link": { + "type": "string", + "example": "https://customvideo.com/join/123456" + }, + "public": { + "type": "boolean" + } + }, + "required": ["type", "link", "public"] + }, + "OutputIntegrationLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "address", + "link", + "integration", + "phone", + "attendeeAddress", + "attendeePhone", + "attendeeDefined", + "conferencing", + "unknown" + ], + "example": "integration", + "description": "only allowed value for type is `integration`" + }, + "integration": { + "type": "string", + "enum": [ + "cal-video", + "google-meet", + "zoom", + "whereby-video", + "whatsapp-video", + "webex-video", + "telegram-video", + "tandem", + "sylaps-video", + "skype-video", + "sirius-video", + "signal-video", + "shimmer-video", + "salesroom-video", + "roam-video", + "riverside-video", + "ping-video", + "office365-video", + "mirotalk-video", + "jitsi", + "jelly-video", + "jelly-conferencing", + "huddle", + "facetime-video", + "element-call-video", + "eightxeight-video", + "discord-video", + "demodesk-video", + "campsite-conferencing", + "campfire-video", + "around-video" + ], + "example": "cal-video" + }, + "link": { + "type": "string" + }, + "credentialId": { + "type": "number" + } + }, + "required": ["type", "integration"] + }, + "OutputPhoneLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "address", + "link", + "integration", + "phone", + "attendeeAddress", + "attendeePhone", + "attendeeDefined" + ], + "example": "phone", + "description": "only allowed value for type is `phone`" + }, + "phone": { + "type": "string", + "example": "+37120993151" + }, + "public": { + "type": "boolean" + } + }, + "required": ["type", "phone", "public"] + }, + "OutputConferencingLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "address", + "link", + "integration", + "phone", + "attendeeAddress", + "attendeePhone", + "attendeeDefined", + "conferencing", + "unknown" + ], + "example": "conferencing", + "description": "only allowed value for type is `conferencing`" + } + }, + "required": ["type"] + }, + "OutputUnknownLocation_2024_06_14": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "address", + "link", + "integration", + "phone", + "attendeeAddress", + "attendeePhone", + "attendeeDefined", + "conferencing", + "unknown" + ], + "example": "unknown", + "description": "only allowed value for type is `unknown`" + }, + "location": { + "type": "string" + } + }, + "required": ["type", "location"] }, "EmailDefaultFieldOutput_2024_06_14": { "type": "object", "properties": { + "type": { + "type": "string", + "enum": [ + "name", + "email", + "phone", + "address", + "text", + "number", + "textarea", + "select", + "multiselect", + "multiemail", + "checkbox", + "radio", + "boolean" + ], + "example": "email", + "description": "only allowed value for type is `email`", + "default": "email" + }, + "label": { + "type": "string" + }, + "placeholder": { + "type": "string" + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if URL contains query parameter `&email=bob@gmail.com`, the email field will be prefilled with this value and disabled." + }, "isDefault": { "type": "object", "default": true, @@ -6331,19 +6801,46 @@ "type": "string", "default": "email" }, - "type": { - "type": "string", - "default": "email" - }, "required": { "type": "boolean" } }, - "required": ["isDefault", "slug", "type", "required"] + "required": ["type", "isDefault", "slug", "required"] }, "NameDefaultFieldOutput_2024_06_14": { "type": "object", "properties": { + "type": { + "type": "string", + "enum": [ + "name", + "email", + "phone", + "address", + "text", + "number", + "textarea", + "select", + "multiselect", + "multiemail", + "checkbox", + "radio", + "boolean" + ], + "example": "name", + "description": "only allowed value for type is `name`", + "default": "name" + }, + "label": { + "type": "string" + }, + "placeholder": { + "type": "string" + }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if URL contains query parameter `&name=bob`, the name field will be prefilled with this value and disabled." + }, "isDefault": { "type": "object", "default": true, @@ -6354,15 +6851,11 @@ "type": "string", "default": "name" }, - "type": { - "type": "string", - "default": "name" - }, "required": { "type": "boolean" } }, - "required": ["isDefault", "slug", "type", "required"] + "required": ["type", "isDefault", "slug", "required"] }, "LocationDefaultFieldOutput_2024_06_14": { "type": "object", @@ -6375,7 +6868,8 @@ }, "slug": { "type": "string", - "default": "location" + "default": "location", + "description": "This booking field is returned only if the event type has more than one location. The purpose of this field is to allow the user to select the location where the event will take place." }, "type": { "type": "string", @@ -6485,6 +6979,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6516,6 +7012,10 @@ "type": "string", "example": "e.g., 1234 Main St" }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `address` and the URL contains query parameter `&address=1234 Main St, London`, the address field will be prefilled with this value and disabled." + }, "isDefault": { "type": "object", "default": false, @@ -6531,6 +7031,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6558,6 +7060,9 @@ "required": { "type": "boolean" }, + "disableOnPrefill": { + "type": "boolean" + }, "isDefault": { "type": "object", "default": false, @@ -6573,6 +7078,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6607,6 +7114,10 @@ "type": "string" } }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `notify-me` and the URL contains query parameter `¬ify-me=true`, the checkbox will be selected and the checkbox field will be disabled." + }, "isDefault": { "type": "object", "default": false, @@ -6622,6 +7133,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6653,6 +7166,10 @@ "type": "string", "example": "e.g., example@example.com" }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `consultants` and the URL contains query parameter `&consultants=alice@gmail.com&consultants=bob@gmail.com`, the these emails will be added and none more can be added." + }, "isDefault": { "type": "object", "default": false, @@ -6668,6 +7185,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6702,6 +7221,10 @@ "type": "string" } }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `consultants` and the URL contains query parameter `&consultants=en&language=it`, the 'en' and 'it' will be selected and the select field will be disabled." + }, "isDefault": { "type": "object", "default": false, @@ -6717,6 +7240,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6748,6 +7273,10 @@ "type": "string", "example": "e.g., 100" }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `calories-per-day` and the URL contains query parameter `&calories-per-day=3000`, the number field will be prefilled with this value and disabled." + }, "isDefault": { "type": "object", "default": false, @@ -6763,6 +7292,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6792,6 +7323,10 @@ "placeholder": { "type": "string" }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `phone` and the URL contains query parameter `&phone=1234567890`, the phone field will be prefilled with this value and disabled." + }, "isDefault": { "type": "object", "default": false, @@ -6807,6 +7342,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6841,6 +7378,10 @@ "type": "string" } }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `language` and options of this select field are ['english', 'italian'] and the URL contains query parameter `&language=italian`, the 'italian' radio buttom will be selected and the select field will be disabled." + }, "isDefault": { "type": "object", "default": false, @@ -6856,6 +7397,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6894,6 +7437,10 @@ "type": "string" } }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `language` and options of this select field are ['english', 'italian'] and the URL contains query parameter `&language=italian`, the 'italian' will be selected and the select field will be disabled." + }, "isDefault": { "type": "object", "default": false, @@ -6909,6 +7456,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6940,6 +7489,10 @@ "type": "string", "example": "e.g., Detailed description here..." }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `dear-diary` and the URL contains query parameter `&dear-diary=Today I shipped a feature`, the text area will be prefilled with this value and disabled." + }, "isDefault": { "type": "object", "default": false, @@ -6955,6 +7508,8 @@ "type": { "type": "string", "enum": [ + "name", + "email", "phone", "address", "text", @@ -6986,6 +7541,10 @@ "type": "string", "example": "e.g., Enter text here" }, + "disableOnPrefill": { + "type": "boolean", + "description": "Disable this booking field if the URL contains query parameter with key equal to the slug and prefill it with the provided value. For example, if the slug is `who-referred-you` and the URL contains query parameter `&who-referred-you=bob`, the text field will be prefilled with this value and disabled." + }, "isDefault": { "type": "object", "default": false, @@ -7006,6 +7565,14 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [15, 30, 60], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -7023,16 +7590,22 @@ "items": { "oneOf": [ { - "$ref": "#/components/schemas/AddressLocation_2024_06_14" + "$ref": "#/components/schemas/OutputAddressLocation_2024_06_14" }, { - "$ref": "#/components/schemas/LinkLocation_2024_06_14" + "$ref": "#/components/schemas/OutputLinkLocation_2024_06_14" }, { - "$ref": "#/components/schemas/IntegrationLocation_2024_06_14" + "$ref": "#/components/schemas/OutputIntegrationLocation_2024_06_14" }, { - "$ref": "#/components/schemas/PhoneLocation_2024_06_14" + "$ref": "#/components/schemas/OutputPhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/OutputConferencingLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/OutputUnknownLocation_2024_06_14" } ] } @@ -7223,6 +7796,7 @@ "required": [ "id", "lengthInMinutes", + "lengthInMinutesOptions", "title", "slug", "description", @@ -7320,6 +7894,14 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [15, 30, 60], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -7338,16 +7920,25 @@ "items": { "oneOf": [ { - "$ref": "#/components/schemas/AddressLocation_2024_06_14" + "$ref": "#/components/schemas/InputAddressLocation_2024_06_14" }, { - "$ref": "#/components/schemas/LinkLocation_2024_06_14" + "$ref": "#/components/schemas/InputLinkLocation_2024_06_14" }, { - "$ref": "#/components/schemas/IntegrationLocation_2024_06_14" + "$ref": "#/components/schemas/InputIntegrationLocation_2024_06_14" }, { - "$ref": "#/components/schemas/PhoneLocation_2024_06_14" + "$ref": "#/components/schemas/InputPhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeeAddressLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeePhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeeDefinedLocation_2024_06_14" } ] } @@ -7531,7 +8122,8 @@ "hideCalendarEventDetails": { "type": "boolean" } - } + }, + "required": ["lengthInMinutesOptions"] }, "UpdateEventTypeOutput_2024_06_14": { "type": "object", @@ -8578,6 +9170,14 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [15, 30, 60], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -8596,16 +9196,25 @@ "items": { "oneOf": [ { - "$ref": "#/components/schemas/AddressLocation_2024_06_14" + "$ref": "#/components/schemas/InputAddressLocation_2024_06_14" }, { - "$ref": "#/components/schemas/LinkLocation_2024_06_14" + "$ref": "#/components/schemas/InputLinkLocation_2024_06_14" }, { - "$ref": "#/components/schemas/IntegrationLocation_2024_06_14" + "$ref": "#/components/schemas/InputIntegrationLocation_2024_06_14" }, { - "$ref": "#/components/schemas/PhoneLocation_2024_06_14" + "$ref": "#/components/schemas/InputPhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeeAddressLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeePhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeeDefinedLocation_2024_06_14" } ] } @@ -8803,7 +9412,7 @@ "description": "If true, all current and future team members will be assigned to this event type" } }, - "required": ["lengthInMinutes", "title", "slug", "schedulingType", "hosts"] + "required": ["lengthInMinutes", "lengthInMinutesOptions", "title", "slug", "schedulingType", "hosts"] }, "CreateTeamEventTypeOutput": { "type": "object", @@ -8865,6 +9474,15 @@ "minimum": 1, "example": 60 }, + "lengthInMinutesOptions": { + "example": [15, 30, 60], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "number", + "minimum": 1 + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -8882,16 +9500,22 @@ "items": { "oneOf": [ { - "$ref": "#/components/schemas/AddressLocation_2024_06_14" + "$ref": "#/components/schemas/OutputAddressLocation_2024_06_14" }, { - "$ref": "#/components/schemas/LinkLocation_2024_06_14" + "$ref": "#/components/schemas/OutputLinkLocation_2024_06_14" }, { - "$ref": "#/components/schemas/IntegrationLocation_2024_06_14" + "$ref": "#/components/schemas/OutputIntegrationLocation_2024_06_14" }, { - "$ref": "#/components/schemas/PhoneLocation_2024_06_14" + "$ref": "#/components/schemas/OutputPhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/OutputConferencingLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/OutputUnknownLocation_2024_06_14" } ] } @@ -9250,6 +9874,14 @@ "type": "number", "example": 60 }, + "lengthInMinutesOptions": { + "example": [15, 30, 60], + "description": "If you want that user can choose between different lengths of the event you can specify them here. Must include the provided `lengthInMinutes`.", + "type": "array", + "items": { + "type": "string" + } + }, "title": { "type": "string", "example": "Learn the secrets of masterchief!" @@ -9268,16 +9900,25 @@ "items": { "oneOf": [ { - "$ref": "#/components/schemas/AddressLocation_2024_06_14" + "$ref": "#/components/schemas/InputAddressLocation_2024_06_14" }, { - "$ref": "#/components/schemas/LinkLocation_2024_06_14" + "$ref": "#/components/schemas/InputLinkLocation_2024_06_14" }, { - "$ref": "#/components/schemas/IntegrationLocation_2024_06_14" + "$ref": "#/components/schemas/InputIntegrationLocation_2024_06_14" }, { - "$ref": "#/components/schemas/PhoneLocation_2024_06_14" + "$ref": "#/components/schemas/InputPhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeeAddressLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeePhoneLocation_2024_06_14" + }, + { + "$ref": "#/components/schemas/InputAttendeeDefinedLocation_2024_06_14" } ] } @@ -9471,7 +10112,8 @@ "type": "boolean", "description": "If true, all current and future team members will be assigned to this event type" } - } + }, + "required": ["lengthInMinutesOptions"] }, "UpdateTeamEventTypeOutput": { "type": "object", @@ -9511,6 +10153,24 @@ }, "required": ["status", "data"] }, + "MembershipUserOutputDto": { + "type": "object", + "properties": { + "avatarUrl": { + "type": "string" + }, + "username": { + "type": "string" + }, + "name": { + "type": "string" + }, + "email": { + "type": "string" + } + }, + "required": ["email"] + }, "OrgTeamMembershipOutputDto": { "type": "object", "properties": { @@ -9532,9 +10192,12 @@ }, "disableImpersonation": { "type": "boolean" + }, + "user": { + "$ref": "#/components/schemas/MembershipUserOutputDto" } }, - "required": ["role", "id", "userId", "teamId", "accepted"] + "required": ["role", "id", "userId", "teamId", "accepted", "user"] }, "OrgTeamMembershipsOutputResponseDto": { "type": "object", @@ -10061,7 +10724,8 @@ "RECORDING_TRANSCRIPTION_GENERATED", "OOO_CREATED", "AFTER_HOSTS_CAL_VIDEO_NO_SHOW", - "AFTER_GUESTS_CAL_VIDEO_NO_SHOW" + "AFTER_GUESTS_CAL_VIDEO_NO_SHOW", + "FORM_SUBMITTED_NO_EVENT" ] }, "active": { @@ -10127,7 +10791,8 @@ "RECORDING_TRANSCRIPTION_GENERATED", "OOO_CREATED", "AFTER_HOSTS_CAL_VIDEO_NO_SHOW", - "AFTER_GUESTS_CAL_VIDEO_NO_SHOW" + "AFTER_GUESTS_CAL_VIDEO_NO_SHOW", + "FORM_SUBMITTED_NO_EVENT" ] }, "active": { @@ -10847,6 +11512,11 @@ "description": "The start time of the booking in ISO 8601 format in UTC timezone.", "example": "2024-08-13T09:00:00Z" }, + "lengthInMinutes": { + "type": "number", + "example": 30, + "description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking." + }, "eventTypeId": { "type": "number", "description": "The ID of the event type that is booked.", @@ -10887,7 +11557,7 @@ } } }, - "required": ["start", "eventTypeId", "attendee"] + "required": ["start", "lengthInMinutes", "eventTypeId", "attendee"] }, "CreateInstantBookingInput_2024_08_13": { "type": "object", @@ -10897,6 +11567,11 @@ "description": "The start time of the booking in ISO 8601 format in UTC timezone.", "example": "2024-08-13T09:00:00Z" }, + "lengthInMinutes": { + "type": "number", + "example": 30, + "description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking." + }, "eventTypeId": { "type": "number", "description": "The ID of the event type that is booked.", @@ -10942,7 +11617,7 @@ "example": true } }, - "required": ["start", "eventTypeId", "attendee", "instant"] + "required": ["start", "lengthInMinutes", "eventTypeId", "attendee", "instant"] }, "CreateRecurringBookingInput_2024_08_13": { "type": "object", @@ -10952,6 +11627,11 @@ "description": "The start time of the booking in ISO 8601 format in UTC timezone.", "example": "2024-08-13T09:00:00Z" }, + "lengthInMinutes": { + "type": "number", + "example": 30, + "description": "If it is an event type that has multiple possible lengths that attendee can pick from, you can pass the desired booking length here.\n If not provided then event type default length will be used for the booking." + }, "eventTypeId": { "type": "number", "description": "The ID of the event type that is booked.", @@ -10973,6 +11653,12 @@ "type": "string" } }, + "meetingUrl": { + "type": "string", + "description": "Deprecated - use 'location' instead. Meeting URL just for this booking. Displayed in email and calendar event. If not provided then cal video link will be generated.", + "example": "https://example.com/meeting", + "deprecated": true + }, "location": { "type": "string", "description": "Location for this booking. Displayed in email and calendar event.", @@ -10980,13 +11666,18 @@ }, "bookingFieldsResponses": { "type": "object", - "description": "Booking field responses.", + "description": "Booking field responses consisting of an object with booking field slug as keys and user response as values.", "example": { "customField": "customValue" } + }, + "recurrenceCount": { + "type": "number", + "description": "The number of recurrences. If not provided then event type recurrence count will be used. Can't be more than\n event type recurrence count", + "example": 5 } }, - "required": ["start", "eventTypeId", "attendee"] + "required": ["start", "lengthInMinutes", "eventTypeId", "attendee"] }, "EventType": { "type": "object", @@ -11029,7 +11720,7 @@ }, "status": { "type": "string", - "enum": ["cancelled", "accepted", "rejected", "pending", "rescheduled"], + "enum": ["cancelled", "accepted", "rejected", "pending"], "example": "accepted" }, "cancellationReason": { @@ -11065,6 +11756,20 @@ "eventType": { "$ref": "#/components/schemas/EventType" }, + "meetingUrl": { + "type": "string", + "description": "Deprecated - rely on 'location' field instead.", + "example": "https://example.com/recurring-meeting", + "deprecated": true + }, + "location": { + "type": "string", + "example": "https://example.com/meeting" + }, + "absentHost": { + "type": "boolean", + "example": true + }, "attendees": { "type": "array", "items": { @@ -11078,6 +11783,93 @@ "type": "string" } }, + "bookingFieldsResponses": { + "type": "object", + "description": "Booking field responses consisting of an object with booking field slug as keys and user response as values.", + "example": { + "customField": "customValue" + } + } + }, + "required": [ + "id", + "uid", + "title", + "description", + "hosts", + "status", + "start", + "end", + "duration", + "eventTypeId", + "eventType", + "absentHost", + "attendees" + ] + }, + "RecurringBookingOutput_2024_08_13": { + "type": "object", + "properties": { + "id": { + "type": "number", + "example": 123 + }, + "uid": { + "type": "string", + "example": "booking_uid_123" + }, + "title": { + "type": "string", + "example": "Consultation" + }, + "description": { + "type": "string", + "example": "Learn how to integrate scheduling into marketplace." + }, + "hosts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Host" + } + }, + "status": { + "type": "string", + "enum": ["cancelled", "accepted", "rejected", "pending"], + "example": "accepted" + }, + "cancellationReason": { + "type": "string", + "example": "User requested cancellation" + }, + "reschedulingReason": { + "type": "string", + "example": "User rescheduled the event" + }, + "rescheduledFromUid": { + "type": "string", + "example": "previous_uid_123" + }, + "start": { + "type": "string", + "example": "2024-08-13T15:30:00Z" + }, + "end": { + "type": "string", + "example": "2024-08-13T16:30:00Z" + }, + "duration": { + "type": "number", + "example": 60 + }, + "eventTypeId": { + "type": "number", + "example": 50, + "deprecated": true, + "description": "Deprecated - rely on 'eventType' object containing the id instead." + }, + "eventType": { + "$ref": "#/components/schemas/EventType" + }, "meetingUrl": { "type": "string", "description": "Deprecated - rely on 'location' field instead.", @@ -11092,97 +11884,6 @@ "type": "boolean", "example": true }, - "bookingFieldsResponses": { - "type": "object", - "description": "Booking field responses consisting of an object with booking field slug as keys and user response as values.", - "example": { - "customField": "customValue" - } - } - }, - "required": [ - "id", - "uid", - "title", - "description", - "hosts", - "status", - "start", - "end", - "duration", - "eventTypeId", - "eventType", - "attendees", - "absentHost" - ] - }, - "RecurringBookingOutput_2024_08_13": { - "type": "object", - "properties": { - "id": { - "type": "number", - "example": 456 - }, - "uid": { - "type": "string", - "example": "recurring_uid_123" - }, - "title": { - "type": "string", - "example": "Recurring meeting" - }, - "description": { - "type": "string", - "example": "Learn how to integrate scheduling into marketplace." - }, - "hosts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Host" - } - }, - "status": { - "type": "string", - "enum": ["cancelled", "accepted", "rejected", "pending"], - "example": "pending" - }, - "cancellationReason": { - "type": "string", - "example": "Event was cancelled" - }, - "reschedulingReason": { - "type": "string", - "example": "Event was rescheduled" - }, - "rescheduledFromUid": { - "type": "string", - "example": "previous_recurring_uid_123" - }, - "start": { - "type": "string", - "example": "2024-08-13T15:30:00Z" - }, - "end": { - "type": "string", - "example": "2024-08-13T16:30:00Z" - }, - "duration": { - "type": "number", - "example": 30 - }, - "eventTypeId": { - "type": "number", - "example": 50, - "deprecated": true, - "description": "Deprecated - rely on 'eventType' object containing the id instead." - }, - "eventType": { - "$ref": "#/components/schemas/EventType" - }, - "recurringBookingUid": { - "type": "string", - "example": "recurring_uid_987" - }, "attendees": { "type": "array", "items": { @@ -11190,32 +11891,22 @@ } }, "guests": { - "example": ["guest3@example.com", "guest4@example.com"], + "example": ["guest1@example.com", "guest2@example.com"], "type": "array", "items": { "type": "string" } }, - "meetingUrl": { - "type": "string", - "description": "Deprecated - rely on 'location' field instead.", - "example": "https://example.com/recurring-meeting", - "deprecated": true - }, - "location": { - "type": "string", - "example": "https://example.com/recurring-meeting" - }, - "absentHost": { - "type": "boolean", - "example": false - }, "bookingFieldsResponses": { "type": "object", "description": "Booking field responses consisting of an object with booking field slug as keys and user response as values.", "example": { "customField": "customValue" } + }, + "recurringBookingUid": { + "type": "string", + "example": "recurring_uid_987" } }, "required": [ @@ -11230,9 +11921,9 @@ "duration", "eventTypeId", "eventType", - "recurringBookingUid", + "absentHost", "attendees", - "absentHost" + "recurringBookingUid" ] }, "CreateBookingOutput_2024_08_13": { @@ -11281,6 +11972,18 @@ "items": { "$ref": "#/components/schemas/RecurringBookingOutput_2024_08_13" } + }, + { + "$ref": "#/components/schemas/GetSeatedBookingOutput_2024_08_13" + }, + { + "$ref": "#/components/schemas/GetRecurringSeatedBookingOutput_2024_08_13" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/GetRecurringSeatedBookingOutput_2024_08_13" + } } ], "description": "Booking data, which can be either a BookingOutput object, a RecurringBookingOutput object, or an array of RecurringBookingOutput objects" @@ -11308,6 +12011,12 @@ }, { "$ref": "#/components/schemas/RecurringBookingOutput_2024_08_13" + }, + { + "$ref": "#/components/schemas/GetSeatedBookingOutput_2024_08_13" + }, + { + "$ref": "#/components/schemas/GetRecurringSeatedBookingOutput_2024_08_13" } ] }, @@ -11319,22 +12028,6 @@ }, "required": ["status", "data"] }, - "RescheduleBookingInput_2024_08_13": { - "type": "object", - "properties": { - "start": { - "type": "string", - "description": "Start time in ISO 8601 format for the new booking", - "example": "2024-08-13T10:00:00Z" - }, - "reschedulingReason": { - "type": "string", - "example": "User requested reschedule", - "description": "Reason for rescheduling the booking" - } - }, - "required": ["start"] - }, "RescheduleBookingOutput_2024_08_13": { "type": "object", "properties": { @@ -11350,6 +12043,12 @@ }, { "$ref": "#/components/schemas/RecurringBookingOutput_2024_08_13" + }, + { + "$ref": "#/components/schemas/CreateSeatedBookingOutput_2024_08_13" + }, + { + "$ref": "#/components/schemas/CreateRecurringSeatedBookingOutput_2024_08_13" } ], "description": "Booking data, which can be either a BookingOutput object or a RecurringBookingOutput object" @@ -11357,16 +12056,6 @@ }, "required": ["status", "data"] }, - "CancelBookingInput_2024_08_13": { - "type": "object", - "properties": { - "cancellationReason": { - "type": "string", - "example": "User requested cancellation" - } - }, - "required": ["cancellationReason"] - }, "CancelBookingOutput_2024_08_13": { "type": "object", "properties": { @@ -11388,6 +12077,18 @@ "items": { "$ref": "#/components/schemas/RecurringBookingOutput_2024_08_13" } + }, + { + "$ref": "#/components/schemas/GetSeatedBookingOutput_2024_08_13" + }, + { + "$ref": "#/components/schemas/GetRecurringSeatedBookingOutput_2024_08_13" + }, + { + "type": "array", + "items": { + "$ref": "#/components/schemas/GetRecurringSeatedBookingOutput_2024_08_13" + } } ], "description": "Booking data, which can be either a BookingOutput object, a RecurringBookingOutput object, or an array of RecurringBookingOutput objects" @@ -11441,6 +12142,68 @@ }, "required": ["status", "data"] }, + "ReassignedToDto": { + "type": "object", + "properties": { + "id": { + "type": "number", + "example": 123 + }, + "name": { + "type": "string", + "example": "John Doe" + }, + "email": { + "type": "string", + "example": "john.doe@example.com" + } + }, + "required": ["id", "name", "email"] + }, + "ReassignBookingOutput_2024_08_13": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "success", + "enum": ["success", "error"] + }, + "data": { + "oneOf": [ + { + "$ref": "#/components/schemas/ReassignBookingOutput_2024_08_13" + } + ], + "description": "Booking data, which can be either a ReassignAutoBookingOutput object or a ReassignManualBookingOutput object", + "allOf": [ + { + "$ref": "#/components/schemas/ReassignBookingOutput_2024_08_13" + } + ] + } + }, + "required": ["status", "data"] + }, + "ReassignToUserBookingInput_2024_08_13": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "example": "Host has to take another call", + "description": "Reason for reassigning the booking" + } + } + }, + "DeclineBookingInput_2024_08_13": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "example": "Host has to take another call", + "description": "Reason for declining a booking that requires a confirmation" + } + } + }, "ReserveSlotInput": { "type": "object", "properties": {