Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions apps/sim/app/(landing)/integrations/data/integrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -10784,8 +10784,34 @@
}
],
"operationCount": 4,
"triggers": [],
"triggerCount": 0,
"triggers": [
{
"id": "servicenow_incident_created",
"name": "ServiceNow Incident Created",
"description": "Trigger workflow when a new incident is created in ServiceNow"
},
{
"id": "servicenow_incident_updated",
"name": "ServiceNow Incident Updated",
"description": "Trigger workflow when an incident is updated in ServiceNow"
},
{
"id": "servicenow_change_request_created",
"name": "ServiceNow Change Request Created",
"description": "Trigger workflow when a new change request is created in ServiceNow"
},
{
"id": "servicenow_change_request_updated",
"name": "ServiceNow Change Request Updated",
"description": "Trigger workflow when a change request is updated in ServiceNow"
},
{
"id": "servicenow_webhook",
"name": "ServiceNow Webhook (All Events)",
"description": "Trigger workflow on any ServiceNow webhook event"
}
],
"triggerCount": 5,
"authType": "none",
"category": "tools",
"integrationType": "customer-support",
Expand Down
16 changes: 16 additions & 0 deletions apps/sim/blocks/blocks/servicenow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ServiceNowIcon } from '@/components/icons'
import type { BlockConfig } from '@/blocks/types'
import { IntegrationType } from '@/blocks/types'
import type { ServiceNowResponse } from '@/tools/servicenow/types'
import { getTrigger } from '@/triggers'

export const ServiceNowBlock: BlockConfig<ServiceNowResponse> = {
type: 'servicenow',
Expand Down Expand Up @@ -215,6 +216,11 @@ Output: {"state": "2", "assigned_to": "john.doe", "work_notes": "Assigned and st
condition: { field: 'operation', value: 'servicenow_delete_record' },
required: true,
},
...getTrigger('servicenow_incident_created').subBlocks,
...getTrigger('servicenow_incident_updated').subBlocks,
...getTrigger('servicenow_change_request_created').subBlocks,
...getTrigger('servicenow_change_request_updated').subBlocks,
...getTrigger('servicenow_webhook').subBlocks,
],
tools: {
access: [
Expand Down Expand Up @@ -262,4 +268,14 @@ Output: {"state": "2", "assigned_to": "john.doe", "work_notes": "Assigned and st
success: { type: 'boolean', description: 'Operation success status' },
metadata: { type: 'json', description: 'Operation metadata' },
},
triggers: {
enabled: true,
available: [
'servicenow_incident_created',
'servicenow_incident_updated',
'servicenow_change_request_created',
'servicenow_change_request_updated',
'servicenow_webhook',
],
},
}
2 changes: 2 additions & 0 deletions apps/sim/lib/webhooks/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { outlookHandler } from '@/lib/webhooks/providers/outlook'
import { resendHandler } from '@/lib/webhooks/providers/resend'
import { rssHandler } from '@/lib/webhooks/providers/rss'
import { salesforceHandler } from '@/lib/webhooks/providers/salesforce'
import { servicenowHandler } from '@/lib/webhooks/providers/servicenow'
import { slackHandler } from '@/lib/webhooks/providers/slack'
import { stripeHandler } from '@/lib/webhooks/providers/stripe'
import { telegramHandler } from '@/lib/webhooks/providers/telegram'
Expand Down Expand Up @@ -72,6 +73,7 @@ const PROVIDER_HANDLERS: Record<string, WebhookProviderHandler> = {
outlook: outlookHandler,
rss: rssHandler,
salesforce: salesforceHandler,
servicenow: servicenowHandler,
slack: slackHandler,
stripe: stripeHandler,
telegram: telegramHandler,
Expand Down
57 changes: 57 additions & 0 deletions apps/sim/lib/webhooks/providers/servicenow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { createLogger } from '@sim/logger'
import { NextResponse } from 'next/server'
import type {
AuthContext,
EventMatchContext,
WebhookProviderHandler,
} from '@/lib/webhooks/providers/types'
import { verifyTokenAuth } from '@/lib/webhooks/providers/utils'

const logger = createLogger('WebhookProvider:ServiceNow')

function asRecord(body: unknown): Record<string, unknown> {
return body && typeof body === 'object' && !Array.isArray(body)
? (body as Record<string, unknown>)
: {}
}

export const servicenowHandler: WebhookProviderHandler = {
verifyAuth({ request, requestId, providerConfig }: AuthContext): NextResponse | null {
const secret = providerConfig.webhookSecret as string | undefined
if (!secret?.trim()) {
logger.warn(`[${requestId}] ServiceNow webhook missing webhookSecret — rejecting`)
return new NextResponse('Unauthorized - Webhook secret not configured', { status: 401 })
}

if (
!verifyTokenAuth(request, secret.trim(), 'x-sim-webhook-secret') &&
!verifyTokenAuth(request, secret.trim())
) {
logger.warn(`[${requestId}] ServiceNow webhook secret verification failed`)
return new NextResponse('Unauthorized - Invalid webhook secret', { status: 401 })
}

return null
},

async matchEvent({ webhook, workflow, body, requestId, providerConfig }: EventMatchContext) {
const triggerId = providerConfig.triggerId as string | undefined
if (!triggerId) {
return true
}

const { isServiceNowEventMatch } = await import('@/triggers/servicenow/utils')
const configuredTableName = providerConfig.tableName as string | undefined
const obj = asRecord(body)

if (!isServiceNowEventMatch(triggerId, obj, configuredTableName)) {
logger.debug(
`[${requestId}] ServiceNow event mismatch for trigger ${triggerId}. Skipping execution.`,
{ webhookId: webhook.id, workflowId: workflow.id, triggerId }
)
return false
}

return true
},
}
12 changes: 12 additions & 0 deletions apps/sim/triggers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@ import {
salesforceRecordUpdatedTrigger,
salesforceWebhookTrigger,
} from '@/triggers/salesforce'
import {
servicenowChangeRequestCreatedTrigger,
servicenowChangeRequestUpdatedTrigger,
servicenowIncidentCreatedTrigger,
servicenowIncidentUpdatedTrigger,
servicenowWebhookTrigger,
} from '@/triggers/servicenow'
import { slackWebhookTrigger } from '@/triggers/slack'
import { stripeWebhookTrigger } from '@/triggers/stripe'
import { telegramWebhookTrigger } from '@/triggers/telegram'
Expand Down Expand Up @@ -437,6 +444,11 @@ export const TRIGGER_REGISTRY: TriggerRegistry = {
salesforce_opportunity_stage_changed: salesforceOpportunityStageChangedTrigger,
salesforce_case_status_changed: salesforceCaseStatusChangedTrigger,
salesforce_webhook: salesforceWebhookTrigger,
servicenow_incident_created: servicenowIncidentCreatedTrigger,
servicenow_incident_updated: servicenowIncidentUpdatedTrigger,
servicenow_change_request_created: servicenowChangeRequestCreatedTrigger,
servicenow_change_request_updated: servicenowChangeRequestUpdatedTrigger,
servicenow_webhook: servicenowWebhookTrigger,
stripe_webhook: stripeWebhookTrigger,
telegram_webhook: telegramWebhookTrigger,
typeform_webhook: typeformWebhookTrigger,
Expand Down
37 changes: 37 additions & 0 deletions apps/sim/triggers/servicenow/change_request_created.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ServiceNowIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildChangeRequestOutputs,
buildServiceNowExtraFields,
servicenowSetupInstructions,
servicenowTriggerOptions,
} from '@/triggers/servicenow/utils'
import type { TriggerConfig } from '@/triggers/types'

/**
* ServiceNow Change Request Created Trigger
*/
export const servicenowChangeRequestCreatedTrigger: TriggerConfig = {
id: 'servicenow_change_request_created',
name: 'ServiceNow Change Request Created',
provider: 'servicenow',
description: 'Trigger workflow when a new change request is created in ServiceNow',
version: '1.0.0',
icon: ServiceNowIcon,

subBlocks: buildTriggerSubBlocks({
triggerId: 'servicenow_change_request_created',
triggerOptions: servicenowTriggerOptions,
setupInstructions: servicenowSetupInstructions('Insert (record creation)'),
extraFields: buildServiceNowExtraFields('servicenow_change_request_created'),
}),

outputs: buildChangeRequestOutputs(),

webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
}
37 changes: 37 additions & 0 deletions apps/sim/triggers/servicenow/change_request_updated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ServiceNowIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildChangeRequestOutputs,
buildServiceNowExtraFields,
servicenowSetupInstructions,
servicenowTriggerOptions,
} from '@/triggers/servicenow/utils'
import type { TriggerConfig } from '@/triggers/types'

/**
* ServiceNow Change Request Updated Trigger
*/
export const servicenowChangeRequestUpdatedTrigger: TriggerConfig = {
id: 'servicenow_change_request_updated',
name: 'ServiceNow Change Request Updated',
provider: 'servicenow',
description: 'Trigger workflow when a change request is updated in ServiceNow',
version: '1.0.0',
icon: ServiceNowIcon,

subBlocks: buildTriggerSubBlocks({
triggerId: 'servicenow_change_request_updated',
triggerOptions: servicenowTriggerOptions,
setupInstructions: servicenowSetupInstructions('Update (record modification)'),
extraFields: buildServiceNowExtraFields('servicenow_change_request_updated'),
}),

outputs: buildChangeRequestOutputs(),

webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
}
40 changes: 40 additions & 0 deletions apps/sim/triggers/servicenow/incident_created.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ServiceNowIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildIncidentOutputs,
buildServiceNowExtraFields,
servicenowSetupInstructions,
servicenowTriggerOptions,
} from '@/triggers/servicenow/utils'
import type { TriggerConfig } from '@/triggers/types'

/**
* ServiceNow Incident Created Trigger
*
* Primary trigger — includes the dropdown for selecting trigger type.
*/
export const servicenowIncidentCreatedTrigger: TriggerConfig = {
id: 'servicenow_incident_created',
name: 'ServiceNow Incident Created',
provider: 'servicenow',
description: 'Trigger workflow when a new incident is created in ServiceNow',
version: '1.0.0',
icon: ServiceNowIcon,

subBlocks: buildTriggerSubBlocks({
triggerId: 'servicenow_incident_created',
triggerOptions: servicenowTriggerOptions,
includeDropdown: true,
setupInstructions: servicenowSetupInstructions('Insert (record creation)'),
extraFields: buildServiceNowExtraFields('servicenow_incident_created'),
}),

outputs: buildIncidentOutputs(),

webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
}
37 changes: 37 additions & 0 deletions apps/sim/triggers/servicenow/incident_updated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { ServiceNowIcon } from '@/components/icons'
import { buildTriggerSubBlocks } from '@/triggers'
import {
buildIncidentOutputs,
buildServiceNowExtraFields,
servicenowSetupInstructions,
servicenowTriggerOptions,
} from '@/triggers/servicenow/utils'
import type { TriggerConfig } from '@/triggers/types'

/**
* ServiceNow Incident Updated Trigger
*/
export const servicenowIncidentUpdatedTrigger: TriggerConfig = {
id: 'servicenow_incident_updated',
name: 'ServiceNow Incident Updated',
provider: 'servicenow',
description: 'Trigger workflow when an incident is updated in ServiceNow',
version: '1.0.0',
icon: ServiceNowIcon,

subBlocks: buildTriggerSubBlocks({
triggerId: 'servicenow_incident_updated',
triggerOptions: servicenowTriggerOptions,
setupInstructions: servicenowSetupInstructions('Update (record modification)'),
extraFields: buildServiceNowExtraFields('servicenow_incident_updated'),
}),

outputs: buildIncidentOutputs(),

webhook: {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
},
}
5 changes: 5 additions & 0 deletions apps/sim/triggers/servicenow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { servicenowChangeRequestCreatedTrigger } from './change_request_created'
export { servicenowChangeRequestUpdatedTrigger } from './change_request_updated'
export { servicenowIncidentCreatedTrigger } from './incident_created'
export { servicenowIncidentUpdatedTrigger } from './incident_updated'
export { servicenowWebhookTrigger } from './webhook'
Loading
Loading