diff --git a/docs/api-reference/v1/openapi-v1.json b/docs/api-reference/v1/openapi-v1.json index c5d9bac7a2..af594e8d76 100644 --- a/docs/api-reference/v1/openapi-v1.json +++ b/docs/api-reference/v1/openapi-v1.json @@ -3938,6 +3938,139 @@ } } }, + "/slots": { + "get": { + "summary": "Get all bookable slots between a datetime range", + "tags": ["slots"], + "parameters": [ + { + "in": "query", + "name": "apiKey", + "required": true, + "description": "Your API Key", + "schema": { + "type": "string", + "example": "cal_live_" + } + }, + { + "in": "query", + "name": "eventTypeId", + "required": false, + "description": "The event type Id to fetch available slots against", + "schema": { + "type": "number" + } + }, + { + "in": "query", + "name": "startTime", + "required": true, + "description": "Start time of the slot lookup", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "in": "query", + "name": "endTime", + "required": true, + "description": "End time of the slot lookup", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "in": "query", + "name": "timeZone", + "description": "TimeZone for the slot lookup", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "usernameList", + "description": "An array of usernames, or team slug in case of a team event [To be used when not using eventTypeId]", + "example": ["user1", "user2", "user3"], + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "style": "form", + "explode": true + }, + { + "in": "query", + "name": "eventTypeSlug", + "description": "Slug of the event type to fetch available slots against [To be used when not using eventTypeId]", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "orgSlug", + "description": "Slug of the organization that the user belongs to, in case the user belongs to an organization [To be used when not using eventTypeId]", + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "isTeamEvent", + "description": "True if the event is a team event", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "example": { + "slots": { + "2024-04-13": [ + { + "time": "2024-04-13T11:00:00+04:00" + }, + { + "time": "2024-04-13T12:00:00+04:00" + }, + { + "time": "2024-04-13T13:00:00+04:00" + } + ] + } + } + } + } + } + }, + "401": { + "description": "Authorization information is missing or invalid.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, + "example": { + "message": "Authorization information is missing or invalid." + } + } + } + } + } + } + }, "/teams": { "get": { "operationId": "listTeams", diff --git a/docs/developing/guides/appstore-and-integration/oauth.mdx b/docs/developing/guides/appstore-and-integration/oauth.mdx new file mode 100644 index 0000000000..80fe58d852 --- /dev/null +++ b/docs/developing/guides/appstore-and-integration/oauth.mdx @@ -0,0 +1,70 @@ +--- +title: "How to use OAuth to authorize apps with Cal.com accounts" +--- + +As an example, you can view our OAuth flow in action on Zapier. Try to connect your cal.com account [here](https://zapier.com/apps/calcom/integrations). +To enable OAuth in one of your apps, you will need a Client ID, Client Secret, Authorization URL, Access Token Request URL, and Refresh Token Request URL. + + + +### OAuth Client Credentials +Only the Cal.com team can create new OAuth clients. Please contact us at [support@cal.com](mailto:support@cal.com) with the following details: client name, redirect URI (provided by the app), app logo, and a link to the app. + +The Cal.com team will register the app and provide you with the Client ID and Client Secret. Keep these credentials confidential and secure. + +### Authorization URL +To initiate the OAuth flow, direct users to the following authorization URL: +- `https://app.cal.com/auth/oauth2/authorize` +- URL Parameters: + - *client_id* + - *state*: A securely generated random string to mitigate CSRF attacks + - *redirect_uri*: This is where users will be redirected after authorization + - *scope*: Specify the required scopes. Current scopes include READ_BOOKING and READ_PROFILE. Additional scopes can be added as needed. + +After users click *Allow*, they will be redirected to the redirect_uri with the code (authorization code) and state as URL parameters. + +### Access Token Request +Endpoint: `POST https://app.Cal.com/api/auth/oauth/token` + +Request Body: +- *code*: The authorization code received in the redirect URI +- *client_id* +- *client_secret* +- *grant_type*: "authorization_code" +- *redirect_uri* + +Response: +``` +{ + access_token: “exampleAccessToken” + refresh_token: “exampleRefreshToken” +} +``` + +### Refresh Token Request +Endpoint: `POST https://app.Cal.com/api/auth/oauth/refreshToken` + +Request Body: +- *grant_type*: "refresh_token" +- *client_id* +- *client_secret* + +Response: +``` +{ + access_token: “exampleAccessToken” +} +``` + +### Testing OAuth Credentials +To verify the correct setup and functionality of OAuth credentials you can use the following endpoint: +`GET https://app.Cal.com/api/auth/oauth/me` + +Headers: +- Authorization: Bearer *exampleAccessToken* + + +### Authorize requests with Bearer token +Ensure that Cal.com endpoints accessed by the app support authentication via Bearer Token. +If this is not the case, it will be necessary to update the code accordingly. +Here is an example of an endpoint that supports both apiKey and Bearer token authentication: [/listBookings endpoint](https://github.com/calcom/cal.com/blob/main/packages/app-store/zapier/api/subscriptions/listBookings.ts) diff --git a/docs/developing/guides/automation/webhooks.mdx b/docs/developing/guides/automation/webhooks.mdx new file mode 100644 index 0000000000..21893a4368 --- /dev/null +++ b/docs/developing/guides/automation/webhooks.mdx @@ -0,0 +1,210 @@ +--- +title: "Webhooks" +--- + + +Webhooks offer a great way to automate the flow with other apps when invitees schedule, cancel or reschedule events, or when the meeting ends. + + +The webhook subscription allows you to listen to specific trigger events, such as when a booking has been scheduled, for example. You can always listen to the webhook by providing a custom subscriber URL with your own development work. However, if you wish to trigger automations without any development work, you can use the integration with Zapier which connects Cal.com to your apps. + + +Please note that the webhooks can be associated with user as well as individual event types, including team event types. + + +### Creating a webhook subscription + +To create a new webhook subscription, visit `/settings/developer/webhooks` and proceed to enter the following details: + + + + This is the listener URL where the payload will be sent when an event trigger is activated. + + + You can choose which specific triggers to listen to. Currently available triggers include: + - `Booking Cancelled` + - `Booking Created` + - `Booking Rescheduled` + - `Booking Rejected` + - `Booking Requested` + - `Booking Payment Initiated` + - `Booking Paid` + - `Meeting Started` + - `Recording Ready` + - `Form Submitted` + - `Meeting Ended` + - `Instant Meeting Created` + + + You can provide a secret key with this webhook to [verify it](/docs/core-features/webhooks#verifying-the-authenticity-of-the-received-payload) on the subscriber URL when receiving a payload. This helps confirm whether the payload is authentic or has been tampered with. You can leave it blank if you don't wish to secure the webhook with a secret key. + + + You have the option to [customize the payload](/docs/core-features/webhooks#adding-a-custom-payload-template) that you receive when a subscribed event is triggered. + + + + +### An example webhook payload + +```json +{ + "triggerEvent": "BOOKING_CREATED", + "createdAt": "2023-05-24T09:30:00.538Z", + "payload": { + "type": "60min", + "title": "60min between Pro Example and John Doe", + "description": "", + "additionalNotes": "", + "customInputs": {}, + "startTime": "2023-05-25T09:30:00Z", + "endTime": "2023-05-25T10:30:00Z", + "organizer": { + "id": 5, + "name": "Pro Example", + "email": "pro@example.com", + "username": "pro", + "timeZone": "Asia/Kolkata", + "language": { + "locale": "en" + }, + "timeFormat": "h:mma" + }, + "responses": { + "name": { + "label": "your_name", + "value": "John Doe" + }, + "email": { + "label": "email_address", + "value": "john.doe@example.com" + }, + "location": { + "label": "location", + "value": { + "optionValue": "", + "value": "inPerson" + } + }, + "notes": { + "label": "additional_notes" + }, + "guests": { + "label": "additional_guests" + }, + "rescheduleReason": { + "label": "reschedule_reason" + } + }, + "userFieldsResponses": {}, + "attendees": [ + { + "email": "john.doe@example.com", + "name": "John Doe", + "timeZone": "Asia/Kolkata", + "language": { + "locale": "en" + } + } + ], + "location": "Calcom HQ", + "destinationCalendar": { + "id": 10, + "integration": "apple_calendar", + "externalId": "https://caldav.icloud.com/1234567/calendars/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/", + "userId": 5, + "eventTypeId": null, + "credentialId": 1 + }, + "hideCalendarNotes": false, + "requiresConfirmation": null, + "eventTypeId": 7, + "seatsShowAttendees": true, + "seatsPerTimeSlot": null, + "uid": "bFJeNb2uX8ANpT3JL5EfXw", + "appsStatus": [ + { + "appName": "Apple Calendar", + "type": "apple_calendar", + "success": 1, + "failures": 0, + "errors": [], + "warnings": [] + } + ], + "eventTitle": "60min", + "eventDescription": "", + "price": 0, + "currency": "usd", + "length": 60, + "bookingId": 91, + "metadata": {}, + "status": "ACCEPTED" + } +} + +``` + +### Verifying the authenticity of the received payload + + + Simply add a new **secret key** to your webhook configuration and save it. + + + The webhook will trigger when an event is created, cancelled, rescheduled, or when a meeting ends. + + + Use the **secret key** to create an HMAC, and update it with the webhook payload received to generate an SHA256 hash. + + + Compare the hash received in the header of the webhook `(X-Cal-Signature-256)` with the one you created using the **secret key** and the body of the payload. If they don't match, the received payload has been adulterated and cannot be trusted. + + + +### Adding a custom payload template + +Customizable webhooks are a great way reduce the development effort and in many cases remove the need for a developer to build an additional integration service. + +An example of a custom payload template is provided here: + +```json +{ + "content": "A new event has been scheduled", + "type": "{{type}}", + "name": "{{title}}", + "organizer": "{{organizer.name}}", + "booker": "{{attendees.0.name}}" +} +``` + +where `{{type}}` represents the event type slug and `{{title}}` represents the title of the event type. Note that the variables should be added with a double parenthesis as shown above. Here’s a breakdown of the payload that you would receive via an incoming webhook, with an exhaustive list of all the supported variables provided below: + +#### Webhook variable list + +| Variable | Type | Description | +|--------------------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| triggerEvent | String | The name of the trigger event [BOOKING_CREATED, BOOKING_RESCHEDULED, BOOKING_CANCELLED, MEETING_ENDED, BOOKING_REJECTED, BOOKING_REQUESTED, BOOKING_PAYMENT_INITIATED, BOOKING_PAID, MEETING_STARTED, RECORDING_READY, FORM_SUBMITTED] | +| createdAt | Datetime | The time of the webhook | +| type | String | The event type slug | +| title | String | The event type name | +| startTime | Datetime | The event's start time | +| endTime | Datetime | The event's end time | +| description | String | The event's description as described in the event type settings | +| location | String | Location of the event | +| organizer | Person | The organizer of the event | +| attendees | Person[] | The event booker & any guests | +| uid | String | The UID of the booking | +| rescheduleUid | String | The UID for rescheduling | +| cancellationReason | String | Reason for cancellation | +| rejectionReason | String | Reason for rejection | +| team.name | String | Name of the team booked | +| team.members | String[] | Members of the team booked | +| metadata | JSON | Contains metadata of the booking, including the meeting URL (videoCallUrl) in case of Google Meet and Cal Video | + + +#### Person Structure +| Variable | Type | Description | +|-----------------|--------|----------------------------------------------------------------------| +| name | String | Name of the individual | +| email | Email | Email of the individual | +| timezone | String | Timezone of the individual (e.g., "America/New_York", "Asia/Kolkata") | +| language?.locale | String | Locale of the individual (e.g., "en", "fr") | diff --git a/docs/developing/introduction.mdx b/docs/developing/introduction.mdx index f6f102670f..54c17b3ca2 100644 --- a/docs/developing/introduction.mdx +++ b/docs/developing/introduction.mdx @@ -3,7 +3,9 @@ title: "Introduction" icon: "presentation-screen" --- - + + + diff --git a/docs/images/i1440x910-pNoAmSPnktzZ_ecaypm.png b/docs/images/i1440x910-pNoAmSPnktzZ_ecaypm.png deleted file mode 100644 index c62f57bbf5..0000000000 Binary files a/docs/images/i1440x910-pNoAmSPnktzZ_ecaypm.png and /dev/null differ diff --git a/docs/images/i1440x910-pNoAmSPnktzZ_ecaypm.webp b/docs/images/i1440x910-pNoAmSPnktzZ_ecaypm.webp new file mode 100644 index 0000000000..069ba3e1c0 Binary files /dev/null and b/docs/images/i1440x910-pNoAmSPnktzZ_ecaypm.webp differ diff --git a/docs/mint.json b/docs/mint.json index 068b41428e..e6b7655e18 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -83,7 +83,8 @@ "pages": [ "developing/guides/appstore-and-integration/build-a-greeter-app", "developing/guides/appstore-and-integration/build-an-app", - "developing/guides/appstore-and-integration/how-to-show-assigned-people-from-a-crm" + "developing/guides/appstore-and-integration/how-to-show-assigned-people-from-a-crm", + "developing/guides/appstore-and-integration/oauth" ] }, { @@ -95,6 +96,11 @@ "developing/guides/auth-and-provision/sso-setup" ] }, + { + "group": "Automation", + "icon": "webhook", + "pages": ["developing/guides/automation/webhooks"] + }, { "group": "Email", "icon": "inbox", @@ -114,7 +120,8 @@ "self-hosting/database-migrations", "self-hosting/upgrading", "self-hosting/sso-setup", - "self-hosting/docker" + "self-hosting/docker", + "self-hosting/license-key" ] }, { diff --git a/docs/self-hosting/license-key.mdx b/docs/self-hosting/license-key.mdx new file mode 100644 index 0000000000..f2c5b3c8f6 --- /dev/null +++ b/docs/self-hosting/license-key.mdx @@ -0,0 +1,16 @@ +--- +title: "License key" +icon: "key" +--- + +If you wish to **self-host** Cal.com with our Commercial License, you need to purchase a License Key to do so. + +You can acquire the license by contacting [cal.com/sales](https://cal.com/sales) + + + +For development environment, please use the following as a localhost license key +``` +59c0bed7-8b21-4280-8514-e022fbfc24c7 +``` + \ No newline at end of file