chore: import upstream snapshot with attribution
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled
Publish CLI Package / publish-npm (push) Has been cancelled
Publish Python SDK / publish-pypi (push) Has been cancelled
Publish TypeScript SDK / publish-npm (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
export { calendlyInviteeCanceledTrigger } from './invitee_canceled'
|
||||
export { calendlyInviteeCreatedTrigger } from './invitee_created'
|
||||
export { calendlyRoutingFormSubmittedTrigger } from './routing_form_submitted'
|
||||
export { calendlyWebhookTrigger } from './webhook'
|
||||
@@ -0,0 +1,76 @@
|
||||
import { CalendlyIcon } from '@/components/icons'
|
||||
import { buildInviteeOutputs } from '@/triggers/calendly/utils'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
|
||||
export const calendlyInviteeCanceledTrigger: TriggerConfig = {
|
||||
id: 'calendly_invitee_canceled',
|
||||
name: 'Calendly Invitee Canceled',
|
||||
provider: 'calendly',
|
||||
description: 'Trigger workflow when someone cancels a scheduled event on Calendly',
|
||||
version: '1.0.0',
|
||||
icon: CalendlyIcon,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'Personal Access Token',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your Calendly personal access token',
|
||||
password: true,
|
||||
required: true,
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_invitee_canceled',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'organization',
|
||||
title: 'Organization URI',
|
||||
type: 'short-input',
|
||||
placeholder: 'https://api.calendly.com/organizations/XXXXXX',
|
||||
description:
|
||||
'Organization URI for the webhook subscription. Get this from "Get Current User" operation.',
|
||||
required: true,
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_invitee_canceled',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'triggerInstructions',
|
||||
title: 'Setup Instructions',
|
||||
hideFromPreview: true,
|
||||
type: 'text',
|
||||
defaultValue: [
|
||||
'<strong>Note:</strong> This trigger requires a paid Calendly subscription (Professional, Teams, or Enterprise plan).',
|
||||
'Get your Personal Access Token from <strong>Settings > Integrations > API & Webhooks</strong> in your Calendly account.',
|
||||
'Use the "Get Current User" operation in a Calendly block to retrieve your Organization URI.',
|
||||
'The webhook will be automatically created in Calendly when you deploy the workflow.',
|
||||
'This webhook triggers when an invitee cancels an event. The payload includes cancellation details and reason.',
|
||||
]
|
||||
.map(
|
||||
(instruction, index) =>
|
||||
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
|
||||
)
|
||||
.join(''),
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_invitee_canceled',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
outputs: buildInviteeOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Calendly-Webhook-Signature': 'v1,signature...',
|
||||
'User-Agent': 'Calendly-Webhook',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import { CalendlyIcon } from '@/components/icons'
|
||||
import { buildInviteeOutputs, calendlyTriggerOptions } from '@/triggers/calendly/utils'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
|
||||
export const calendlyInviteeCreatedTrigger: TriggerConfig = {
|
||||
id: 'calendly_invitee_created',
|
||||
name: 'Calendly Invitee Created',
|
||||
provider: 'calendly',
|
||||
description: 'Trigger workflow when someone schedules a new event on Calendly',
|
||||
version: '1.0.0',
|
||||
icon: CalendlyIcon,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'selectedTriggerId',
|
||||
title: 'Trigger Type',
|
||||
type: 'dropdown',
|
||||
mode: 'trigger',
|
||||
options: calendlyTriggerOptions,
|
||||
value: () => 'calendly_invitee_created',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'Personal Access Token',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your Calendly personal access token',
|
||||
password: true,
|
||||
required: true,
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_invitee_created',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'organization',
|
||||
title: 'Organization URI',
|
||||
type: 'short-input',
|
||||
placeholder: 'https://api.calendly.com/organizations/XXXXXX',
|
||||
description:
|
||||
'Organization URI for the webhook subscription. Get this from "Get Current User" operation.',
|
||||
required: true,
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_invitee_created',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'triggerInstructions',
|
||||
title: 'Setup Instructions',
|
||||
hideFromPreview: true,
|
||||
type: 'text',
|
||||
defaultValue: [
|
||||
'<strong>Note:</strong> This trigger requires a paid Calendly subscription (Professional, Teams, or Enterprise plan).',
|
||||
'Get your Personal Access Token from <strong>Settings > Integrations > API & Webhooks</strong> in your Calendly account.',
|
||||
'Use the "Get Current User" operation in a Calendly block to retrieve your Organization URI.',
|
||||
'The webhook will be automatically created in Calendly when you deploy the workflow.',
|
||||
'This webhook triggers when an invitee schedules a new event. Rescheduling triggers both cancellation and creation events.',
|
||||
]
|
||||
.map(
|
||||
(instruction, index) =>
|
||||
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
|
||||
)
|
||||
.join(''),
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_invitee_created',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
outputs: buildInviteeOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Calendly-Webhook-Signature': 'v1,signature...',
|
||||
'User-Agent': 'Calendly-Webhook',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import { CalendlyIcon } from '@/components/icons'
|
||||
import { buildRoutingFormOutputs } from '@/triggers/calendly/utils'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
|
||||
export const calendlyRoutingFormSubmittedTrigger: TriggerConfig = {
|
||||
id: 'calendly_routing_form_submitted',
|
||||
name: 'Calendly Routing Form Submitted',
|
||||
provider: 'calendly',
|
||||
description: 'Trigger workflow when someone submits a Calendly routing form',
|
||||
version: '1.0.0',
|
||||
icon: CalendlyIcon,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'Personal Access Token',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your Calendly personal access token',
|
||||
password: true,
|
||||
required: true,
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_routing_form_submitted',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'organization',
|
||||
title: 'Organization URI',
|
||||
type: 'short-input',
|
||||
placeholder: 'https://api.calendly.com/organizations/XXXXXX',
|
||||
description:
|
||||
'Organization URI for the webhook subscription. Get this from "Get Current User" operation.',
|
||||
required: true,
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_routing_form_submitted',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'triggerInstructions',
|
||||
title: 'Setup Instructions',
|
||||
hideFromPreview: true,
|
||||
type: 'text',
|
||||
defaultValue: [
|
||||
'<strong>Note:</strong> This trigger requires a paid Calendly subscription (Professional, Teams, or Enterprise plan).',
|
||||
'Get your Personal Access Token from <strong>Settings > Integrations > API & Webhooks</strong> in your Calendly account.',
|
||||
'Use the "Get Current User" operation in a Calendly block to retrieve your Organization URI.',
|
||||
'The webhook will be automatically created in Calendly when you deploy the workflow.',
|
||||
'This webhook triggers when someone submits a routing form, regardless of whether they book an event.',
|
||||
]
|
||||
.map(
|
||||
(instruction, index) =>
|
||||
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
|
||||
)
|
||||
.join(''),
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_routing_form_submitted',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
outputs: buildRoutingFormOutputs(),
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Calendly-Webhook-Signature': 'v1,signature...',
|
||||
'User-Agent': 'Calendly-Webhook',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
import type { TriggerOutput } from '@/triggers/types'
|
||||
|
||||
/**
|
||||
* Shared trigger dropdown options for all Calendly triggers
|
||||
*/
|
||||
export const calendlyTriggerOptions = [
|
||||
{ label: 'Invitee Created', id: 'calendly_invitee_created' },
|
||||
{ label: 'Invitee Canceled', id: 'calendly_invitee_canceled' },
|
||||
{ label: 'Routing Form Submitted', id: 'calendly_routing_form_submitted' },
|
||||
{ label: 'General Webhook (All Events)', id: 'calendly_webhook' },
|
||||
]
|
||||
|
||||
/**
|
||||
* Generate setup instructions for a specific Calendly event type
|
||||
*/
|
||||
export function calendlySetupInstructions(eventType: string, additionalNotes?: string): string {
|
||||
const instructions = [
|
||||
'<strong>Note:</strong> Webhooks require a paid Calendly subscription (Professional, Teams, or Enterprise plan).',
|
||||
'<strong>Important:</strong> Calendly does not provide a UI for creating webhooks. You must create them programmatically using the API. See the <a href="https://developer.calendly.com/api-docs" target="_blank" rel="noopener noreferrer">Calendly Developer documentation</a> for details.',
|
||||
'Get your Calendly <strong>Personal Access Token</strong> from the Calendly dashboard under <strong>Integrations > API & Webhooks</strong>.',
|
||||
'In your workflow, add a Calendly block and select the <strong>"Create Webhook"</strong> operation.',
|
||||
'Enter your Personal Access Token in the Calendly block.',
|
||||
'Copy the <strong>Webhook URL</strong> shown above and paste it into the webhook URL field in the Create Webhook operation.',
|
||||
`Select the event types to monitor. For this trigger, select <strong>${eventType}</strong>.`,
|
||||
'Set the scope to <strong>Organization</strong> or <strong>User</strong> as needed (routing form submissions require organization scope).',
|
||||
'Run the workflow to create the webhook subscription. You can use the "List Webhooks" operation to verify it was created.',
|
||||
]
|
||||
|
||||
if (additionalNotes) {
|
||||
instructions.push(additionalNotes)
|
||||
}
|
||||
|
||||
return instructions
|
||||
.map(
|
||||
(instruction, index) =>
|
||||
`<div class="mb-3">${index === 0 ? instruction : `<strong>${index}.</strong> ${instruction}`}</div>`
|
||||
)
|
||||
.join('')
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared tracking output schema
|
||||
*/
|
||||
export const trackingOutputs = {
|
||||
utm_campaign: {
|
||||
type: 'string',
|
||||
description: 'UTM campaign parameter',
|
||||
},
|
||||
utm_source: {
|
||||
type: 'string',
|
||||
description: 'UTM source parameter',
|
||||
},
|
||||
utm_medium: {
|
||||
type: 'string',
|
||||
description: 'UTM medium parameter',
|
||||
},
|
||||
utm_content: {
|
||||
type: 'string',
|
||||
description: 'UTM content parameter',
|
||||
},
|
||||
utm_term: {
|
||||
type: 'string',
|
||||
description: 'UTM term parameter',
|
||||
},
|
||||
salesforce_uuid: {
|
||||
type: 'string',
|
||||
description: 'Salesforce UUID',
|
||||
},
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Shared questions and answers output schema
|
||||
*/
|
||||
export const questionsAndAnswersOutputs = {
|
||||
type: 'array',
|
||||
description: 'Questions and answers from the booking form',
|
||||
items: {
|
||||
question: {
|
||||
type: 'string',
|
||||
description: 'Question text',
|
||||
},
|
||||
answer: {
|
||||
type: 'string',
|
||||
description: 'Answer text',
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
/**
|
||||
* Build output schema for invitee events
|
||||
*/
|
||||
export function buildInviteeOutputs(): Record<string, TriggerOutput> {
|
||||
return {
|
||||
event: {
|
||||
type: 'string',
|
||||
description: 'Event type (invitee.created or invitee.canceled)',
|
||||
},
|
||||
created_at: {
|
||||
type: 'string',
|
||||
description: 'Webhook event creation timestamp',
|
||||
},
|
||||
created_by: {
|
||||
type: 'string',
|
||||
description: 'URI of the Calendly user who created this webhook',
|
||||
},
|
||||
payload: {
|
||||
uri: {
|
||||
type: 'string',
|
||||
description: 'Invitee URI',
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
description: 'Invitee email address',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Invitee full name',
|
||||
},
|
||||
first_name: {
|
||||
type: 'string',
|
||||
description: 'Invitee first name',
|
||||
},
|
||||
last_name: {
|
||||
type: 'string',
|
||||
description: 'Invitee last name',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
description: 'Invitee status (active or canceled)',
|
||||
},
|
||||
timezone: {
|
||||
type: 'string',
|
||||
description: 'Invitee timezone',
|
||||
},
|
||||
event: {
|
||||
type: 'string',
|
||||
description: 'Scheduled event URI',
|
||||
},
|
||||
questions_and_answers: questionsAndAnswersOutputs,
|
||||
tracking: trackingOutputs,
|
||||
text_reminder_number: {
|
||||
type: 'string',
|
||||
description: 'Phone number for text reminders',
|
||||
},
|
||||
rescheduled: {
|
||||
type: 'boolean',
|
||||
description: 'Whether this invitee rescheduled',
|
||||
},
|
||||
old_invitee: {
|
||||
type: 'string',
|
||||
description: 'URI of the old invitee (if rescheduled)',
|
||||
},
|
||||
new_invitee: {
|
||||
type: 'string',
|
||||
description: 'URI of the new invitee (if rescheduled)',
|
||||
},
|
||||
cancel_url: {
|
||||
type: 'string',
|
||||
description: 'URL to cancel the event',
|
||||
},
|
||||
reschedule_url: {
|
||||
type: 'string',
|
||||
description: 'URL to reschedule the event',
|
||||
},
|
||||
created_at: {
|
||||
type: 'string',
|
||||
description: 'Invitee creation timestamp',
|
||||
},
|
||||
updated_at: {
|
||||
type: 'string',
|
||||
description: 'Invitee last update timestamp',
|
||||
},
|
||||
canceled: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the event was canceled',
|
||||
},
|
||||
cancellation: {
|
||||
type: 'object',
|
||||
description: 'Cancellation details',
|
||||
properties: {
|
||||
canceled_by: {
|
||||
type: 'string',
|
||||
description: 'Who canceled the event',
|
||||
},
|
||||
reason: {
|
||||
type: 'string',
|
||||
description: 'Cancellation reason',
|
||||
},
|
||||
},
|
||||
},
|
||||
payment: {
|
||||
type: 'object',
|
||||
description: 'Payment details',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: 'Payment ID',
|
||||
},
|
||||
provider: {
|
||||
type: 'string',
|
||||
description: 'Payment provider',
|
||||
},
|
||||
amount: {
|
||||
type: 'number',
|
||||
description: 'Payment amount',
|
||||
},
|
||||
currency: {
|
||||
type: 'string',
|
||||
description: 'Payment currency',
|
||||
},
|
||||
terms: {
|
||||
type: 'string',
|
||||
description: 'Payment terms',
|
||||
},
|
||||
successful: {
|
||||
type: 'boolean',
|
||||
description: 'Whether payment was successful',
|
||||
},
|
||||
},
|
||||
},
|
||||
no_show: {
|
||||
type: 'object',
|
||||
description: 'No-show details',
|
||||
properties: {
|
||||
created_at: {
|
||||
type: 'string',
|
||||
description: 'No-show marked timestamp',
|
||||
},
|
||||
},
|
||||
},
|
||||
reconfirmation: {
|
||||
type: 'object',
|
||||
description: 'Reconfirmation details',
|
||||
properties: {
|
||||
created_at: {
|
||||
type: 'string',
|
||||
description: 'Reconfirmation timestamp',
|
||||
},
|
||||
confirmed_at: {
|
||||
type: 'string',
|
||||
description: 'Confirmation timestamp',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as any
|
||||
}
|
||||
|
||||
/**
|
||||
* Build output schema for routing form submission events
|
||||
*/
|
||||
export function buildRoutingFormOutputs(): Record<string, TriggerOutput> {
|
||||
return {
|
||||
event: {
|
||||
type: 'string',
|
||||
description: 'Event type (routing_form_submission.created)',
|
||||
},
|
||||
created_at: {
|
||||
type: 'string',
|
||||
description: 'Webhook event creation timestamp',
|
||||
},
|
||||
created_by: {
|
||||
type: 'string',
|
||||
description: 'URI of the Calendly user who created this webhook',
|
||||
},
|
||||
payload: {
|
||||
uri: {
|
||||
type: 'string',
|
||||
description: 'Routing form submission URI',
|
||||
},
|
||||
routing_form: {
|
||||
type: 'string',
|
||||
description: 'Routing form URI',
|
||||
},
|
||||
submitter: {
|
||||
type: 'object',
|
||||
description: 'Submitter details',
|
||||
properties: {
|
||||
uri: {
|
||||
type: 'string',
|
||||
description: 'Submitter URI',
|
||||
},
|
||||
email: {
|
||||
type: 'string',
|
||||
description: 'Submitter email address',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'Submitter full name',
|
||||
},
|
||||
},
|
||||
},
|
||||
submitter_type: {
|
||||
type: 'string',
|
||||
description: 'Type of submitter',
|
||||
},
|
||||
questions_and_answers: questionsAndAnswersOutputs,
|
||||
tracking: trackingOutputs,
|
||||
result: {
|
||||
type: 'object',
|
||||
description: 'Routing result details',
|
||||
properties: {
|
||||
type: {
|
||||
type: 'string',
|
||||
description: 'Result type (event_type, custom_message, or external_url)',
|
||||
},
|
||||
value: {
|
||||
type: 'string',
|
||||
description: 'Result value (event type URI, message, or URL)',
|
||||
},
|
||||
},
|
||||
},
|
||||
created_at: {
|
||||
type: 'string',
|
||||
description: 'Submission creation timestamp',
|
||||
},
|
||||
updated_at: {
|
||||
type: 'string',
|
||||
description: 'Submission last update timestamp',
|
||||
},
|
||||
},
|
||||
} as any
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Calendly event matches the expected trigger configuration
|
||||
*/
|
||||
export function isCalendlyEventMatch(triggerId: string, eventType: string): boolean {
|
||||
const eventMap: Record<string, string> = {
|
||||
calendly_invitee_created: 'invitee.created',
|
||||
calendly_invitee_canceled: 'invitee.canceled',
|
||||
calendly_routing_form_submitted: 'routing_form_submission.created',
|
||||
}
|
||||
|
||||
const expectedEvent = eventMap[triggerId]
|
||||
if (!expectedEvent) {
|
||||
return true // Unknown trigger or general webhook, allow through
|
||||
}
|
||||
|
||||
return expectedEvent === eventType
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
import { CalendlyIcon } from '@/components/icons'
|
||||
import type { TriggerConfig } from '@/triggers/types'
|
||||
|
||||
export const calendlyWebhookTrigger: TriggerConfig = {
|
||||
id: 'calendly_webhook',
|
||||
name: 'Calendly Webhook',
|
||||
provider: 'calendly',
|
||||
description: 'Trigger workflow from any Calendly webhook event',
|
||||
version: '1.0.0',
|
||||
icon: CalendlyIcon,
|
||||
|
||||
subBlocks: [
|
||||
{
|
||||
id: 'apiKey',
|
||||
title: 'Personal Access Token',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter your Calendly personal access token',
|
||||
password: true,
|
||||
required: true,
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_webhook',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'organization',
|
||||
title: 'Organization URI',
|
||||
type: 'short-input',
|
||||
placeholder: 'https://api.calendly.com/organizations/XXXXXX',
|
||||
description:
|
||||
'Organization URI for the webhook subscription. Get this from "Get Current User" operation.',
|
||||
required: true,
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_webhook',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'triggerInstructions',
|
||||
title: 'Setup Instructions',
|
||||
hideFromPreview: true,
|
||||
type: 'text',
|
||||
defaultValue: [
|
||||
'<strong>Note:</strong> This trigger requires a paid Calendly subscription (Professional, Teams, or Enterprise plan).',
|
||||
'Get your Personal Access Token from <strong>Settings > Integrations > API & Webhooks</strong> in your Calendly account.',
|
||||
'Use the "Get Current User" operation in a Calendly block to retrieve your Organization URI.',
|
||||
'The webhook will be automatically created in Calendly when you deploy the workflow.',
|
||||
'This webhook subscribes to all Calendly events (invitee created, invitee canceled, and routing form submitted). Use the <code>event</code> field in the payload to determine the event type.',
|
||||
]
|
||||
.map(
|
||||
(instruction, index) =>
|
||||
`<div class="mb-3"><strong>${index + 1}.</strong> ${instruction}</div>`
|
||||
)
|
||||
.join(''),
|
||||
mode: 'trigger',
|
||||
condition: {
|
||||
field: 'selectedTriggerId',
|
||||
value: 'calendly_webhook',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
outputs: {
|
||||
event: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Event type (invitee.created, invitee.canceled, or routing_form_submission.created)',
|
||||
},
|
||||
created_at: {
|
||||
type: 'string',
|
||||
description: 'Webhook event creation timestamp',
|
||||
},
|
||||
created_by: {
|
||||
type: 'string',
|
||||
description: 'URI of the Calendly user who created this webhook',
|
||||
},
|
||||
payload: {
|
||||
type: 'object',
|
||||
description: 'Complete event payload (structure varies by event type)',
|
||||
},
|
||||
},
|
||||
|
||||
webhook: {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Calendly-Webhook-Signature': 'v1,signature...',
|
||||
'User-Agent': 'Calendly-Webhook',
|
||||
},
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user