Webhooks

Jul 2, 2021

About Webhooks

A webhook is a way for an app to send data to other apps based on an event trigger.

Learn about the Pipeline webhooks, how to setup it up, and how to extract data from the payload.

Getting started

Setup a webhook

You can setup webhooks using Flow Rules using the event triggers.

A common use-case is sending a webhook to your endpoint whenever a new Ask is created. The rule configuration looks like the following:

To ensure security, Pipeline webhooks require HTTPS endpoints. HTTP endpoint is not allowed.

Note, your webhook endpoint must be accessible by Pipeline. By default, Pipeline cannot access an endpoint that requires authentication. If your endpoint requires authentication, please contact our support team to request customization.

Test Signature

Use the following parameters to make sure your signature validator is working correctly.

AES Encryption Parameters:

Mode CBC
IV Init Vector IV16
Key Size 128 bits

Webhook Parameters:

Time 1616787950772
Digest 6BciKizahTvXKQBw
From shrutefarms.pipelineapp.io
To mockbin.org

Webhook Signature wfKE8Zr7ZxVZCzNPvnVs98IlHtAw7bSVWxPntvl5f3b/0AJ8wi/I3l77GlHx0ZQ5exT8QMMsT+zUEfzNcx4U/g==

Test using online AES tool »

Validate the webhook signature

We HIGHLY recommend that you validate the webhook signature.

A Pipeline webhook sends 3 HTTP headers for security and validation:

  • X-PL-TIME Timestamp of the webhook in Unix epoch milliseconds
  • X-PL-DIGEST Digest to decrypt the signature
  • X-PL-SIGNATURE Webhook signature

The webhook signature is an AES encrypted, | delimited string of the timestamp (Unix epoch in milliseconds), destination domain name, and origin domain name of the webhook, ex: 1616787950772|mockbin.org|shrutefarms.pipelineapp.io

Use the Digest to decrypt the signature and validate the timestamp and origin domain name in the signature against the time in the HTTP header and the referring domain.

Make sure the data in the signature match the data in the HTTP header.

In addition, you can use the timestamp to ensure you protect against replay attacks.

Reviewing the payload

The data in the webhook is a JSON payload based on the RequestType with the following:

{
    "requestStatusName": "Open",
    "process": {
	"processName": "Test flow",
	"processCode": "TCK124RLNA99",
	"isArchive": 0
    },
    "requestComment": "",
    "requestCode": "GFK3ARE861",
    "requestName": "test ask",
    "requestDateStamp": 1601941558050,
    "currentStepId": 44258,
    "currentStepCode": "QZM44258FGXIXF",
    "requestRecurrenceId": 0,
    "totalSteps": 3,
    "completedStepCount": 0,
    "totalTodoSteps": 3,
    "currentProcessStepOwnerTeamName": "N/A",
    "isDelayed": false,
    "useDueDates": false,
    "originalDueDateStamp": 1601941558050,
    "currentDueDateStamp": 1601941558050,
    "requester": {
	"contactFirstName": "Henry",
	"contactLastName": "Evans",
	"contactEmail": "henry.evans@company.com",
	"contactCode": "GYD6GR6W18",
	"isTrash": false
    },
    "workflowOwner": {
	"contactFirstName": "",
	"contactLastName": "",
	"contactEmail": "",
	"contactCode": "",
	"type": "Team",
	"contactProfileImageUrl": "",
	"contactPoolProfileImageUrl": "",
	"contactPoolName": "Test Team",
	"contactPoolCode": "SNY30P4M48N",
	"contactIsMe": false,
	"isMember": 1,
	"isOwner": 1,
	"isTrash": false,
	"members": [
	    {
		"contactFirstName": "Henry",
		"contactLastName": "Evans",
		"contactEmail": "henry.evans@company.com",
		"contactCode": "GYD6GR6W18",
		"isTrash": false
	    }
	]
    },
    "form": {
	"formId": 604,
	"fields": [
	    {
		"fieldCode": "3B104627-7182-40A2-8134-8A68FD6B49D7",
		"editableFieldValue": "Henry",
		"fieldTitle": "First Name",
		"fieldType": "TEXT",
		"fieldValue": "Henry",
		"fieldName": "contact_first_name",
		"metDependency": true,
		"childFields": null
	    },
	    {
		"fieldCode": "E9E8FA01-52FA-40A5-94FE-4FF61F46F8E0",
		"editableFieldValue": "Evans",
		"fieldTitle": "Last Name",
		"fieldType": "TEXT",
		"fieldValue": "Evans",
		"fieldName": "contact_last_name",
		"metDependency": true,
		"childFields": null
	    },
	    {
		"fieldCode": "792E449C-4587-4856-AED3-B1A20465C0B2",
		"editableFieldValue": "henry.evans@company.com",
		"fieldTitle": "Email",
		"fieldType": "TEXT",
		"fieldValue": "henry.evans@company.com",
		"fieldName": "contact_email",
		"metDependency": true,
		"childFields": null
	    },
	    {
		"fieldCode": "D53FFC90-23F2-432A-A974-468FF8F8A441",
		"editableFieldValue": "test ask",
		"fieldTitle": "Ask",
		"fieldType": "TEXT",
		"fieldValue": "test ask",
		"fieldName": "request_name",
		"metDependency": true,
		"childFields": null
	    },
	    {
		"fieldCode": "253FEFE2-E8AE-4606-BC94-B7F67DF99FCD",
		"editableFieldValue": "",
		"fieldTitle": "Details",
		"fieldType": "TEXTAREA",
		"fieldValue": "",
		"fieldName": "details_notes_or_comments",
		"metDependency": true,
		"childFields": null
	    },
	    {
		"fieldCode": "53789D90-E479-4091-ADDE-24C48D0CC58D",
		"editableFieldValue": "",
		"fieldTitle": "Files",
		"fieldType": "FILEUPLOAD",
		"fieldValue": "",
		"fieldName": "request_files",
		"metDependency": true,
		"childFields": null
	    }
	]
    },
    "attachments": [],
    "currentStepRename": {
	"stepCode": "QZM44258FGXIXF",
	"stepName": "Execute step 1",
	"stepStatusName": " NA",
	"dueDateTimeToComplete": 1,
	"dueDateStamp": 1601941558147,
	"useDueDates": false,
	"isPastDue": false,
	"stepOrder": 1,
	"isAdHocStep": false,
	"isExternal": 0,
	"isSkippable": 0,
	"isConfidential": 0,
	"stepCreateDateStamp": 1601941560000.0,
	"stepStartDateStamp": 1601941560000.0,
	"requestCode": "GFK3ARE861",
	"canReassignStep": true,
	"canSendReminder": true,
	"stepOwner": {
	    "contactFirstName": "Henry",
	    "contactLastName": "Evans",
	    "contactEmail": "henry.evans@company.com",
	    "contactCode": "GYD6GR6W18",
	    "type": "Contact",
	    "contactProfileImageUrl": "https://d1v1s76gnntd7e.cloudfront.net/pipeline/contact-blank.png",
	    "contactPoolProfileImageUrl": "",
	    "contactPoolName": "",
	    "contactPoolCode": "",
	    "contactIsMe": true,
	    "isMember": 0,
	    "isOwner": 0,
	    "isTrash": false,
	    "members": []
	}
    }
}

If you need more details (ex: all steps, activity feed, etc.), please use the getRequest query from the API.

Back to Top