orchestrator
2022.10
false
UiPath logo, featuring letters U and I in white
Orchestrator User Guide
Automation CloudAutomation Cloud Public SectorAutomation SuiteStandalone
Last updated Oct 17, 2024

Webhooks

Webhooks enable you to better integrate your UiPath automation with your entire application ecosystem. You can subscribe to Orchestrator events and send them to any external DCM, BPM, or CRM solution and inform different users, for example, that there is a new queue item that can be processed, a trigger has failed, or a process has been updated.

Webhooks allow external systems to subscribe and listen to different types of Orchestrator events. The Webhooks page enables you to easily set them up and view the ones that have been previously created. You can also disable webhooks, search for a specific one, edit or delete them.

Events are available for jobs, robots, queues, queue items, processes, and triggers.

Each event sends a payload to a specified URL containing information. Some properties are common for all, while others are particular to each event type.

Webhook events are created per folder, so if you have a webhook event associated to a resource that is shared across folders, such as a queue, a separate webhook event is generated for each of those folders.

If the request to forward an event fails, the circuit breaker for that particular webhook opens, disabling the webhook for one hour.

Note:
  • Any webhook events that should have been sent while the circuit breaker is open are skipped and not retried once the circuit breaker closes.
  • Webhook events are not stored, and cannot be retried or exported. Furthermore, if the call to the external platform fails, the event is lost. Webhooks are designed for real-time processing.

Common Payload Properties

Property Name

Property Type

Description and Example

Type

string

The event type that triggered the notification.

This property is displayed for all types of events.

Example:

"Type": "job.created"

"Type":"process.updated"

EventId

string

An identifier uniquely generated for each event when it occurred.

This property is displayed for all types of events.

Example:

"EventId":"3e5af0113e674ae597c579cb35ed8630"

Timestamp

RFC 8601 date

The date and time at which the event was generated.

This property is displayed for all types of events.

Example:

"Timestamp":"2018-11-02T11:47:48.5790797Z"

TenantId

integer

The id of the tenant on which the event was generated. The default tenant is 1.

This property is displayed for all types of events.

Example:

"TenantId":3

UserId

integer

The user id whose action triggered the event.

This parameter is not displayed if the event is triggered by either a Robot or a trigger.

This property is displayed for all types of events.

Example:

"UserId": 4947

FolderId

integer

The id of the folder in which the event was generated.

This parameter is not displayed for events triggered by modern robots.

Example:

"FolderId": 26

Permissions

To perform various operations on the Webhooks page, you need to be granted the corresponding permissions on webhooks:

  • View - Enables you to view webhooks and their details, as well as retrieve them using the API, send a ping request, or get the list of all the events a webhook can subscribe to.
  • Create - This permission enables you to add new webhooks. Please note that you also require View permissions.
  • Edit - Grants you the right to edit webhooks from the UI or by using the API. Please note that you also require View permissions.
  • Delete - A permission that enables you to delete webhooks. Please note that you also require View permissions.

Authentication

All webhook HTTP requests use the secret you add when creating a webhook to authenticate. It is combined with the request body using an HMAC-SHA256 keyed hash. This results in a secure signature that does not contain any secret information, is unique to each request, and is sent through the X-UiPath-Signature HTTP header.

Client apps that receive Orchestrator requests must check the requests' authenticity. The request signing follows the following pattern:

  • The client app receives a webhook request from Orchestrator;
  • The client app computes a signature based on the request;
  • The client app tries to match the signature it computed with the request signature:

    • If the signatures do not match, the client app should not process the request.
    • If the signatures match, the client app should process the request.

Computing the signature should be done as follows:

  1. Retrieve the X-UiPath-Signature HTTP header.
  2. To obtain the raw signature bytes, decode the value of the header from Base64.
  3. Retrieve the raw request body.

    Note: Orchestrator requests are always encoded using UTF-8.
  4. Compute the hash using SHA256 and the signing key (UTF-8 encoded).
  5. Compare the computed signature to the value from X-UiPath-Signature HTTP header:
    • If the signatures do not match, do not process the request.
    • If the signatures match, the client app should process the request.

Signature Validation Examples

using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
 
 
public async Task<bool> IsValidRequestAsync(HttpRequestMessage request, string secret)
{
    if (!request.Headers.TryGetValues("X-UiPath-Signature", out var headerValues))
        return false;
 
    var orchestratorSignature = Convert.FromBase64String(headerValues.First());
    using (var sha = new HMACSHA256(key: Encoding.UTF8.GetBytes(secret)))
    {
        var computedSignature = sha.ComputeHash(await request.Content.ReadAsByteArrayAsync());
        return ByteArrayEquals(orchestratorSignature, computedSignature);
    }
}using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
 
 
public async Task<bool> IsValidRequestAsync(HttpRequestMessage request, string secret)
{
    if (!request.Headers.TryGetValues("X-UiPath-Signature", out var headerValues))
        return false;
 
    var orchestratorSignature = Convert.FromBase64String(headerValues.First());
    using (var sha = new HMACSHA256(key: Encoding.UTF8.GetBytes(secret)))
    {
        var computedSignature = sha.ComputeHash(await request.Content.ReadAsByteArrayAsync());
        return ByteArrayEquals(orchestratorSignature, computedSignature);
    }
}
const { createServer } = require('http');
const { createHmac } = require('crypto');
 
const PORT = 9090
const WEBHOOK_SECRET = '<same secret as configured in Orchestrator>'
 
const isValidRequest = (body /* Buffer */, secret /* string */, expectedSignature /* string */) =>
    expectedSignature == null || createHmac('sha256', secret)
        .update(body)
        .digest('base64') === expectedSignature
 
const server = createServer((req, resp) => {
 
    let body = new Buffer([])
 
    req.on('data', chunk => body = Buffer.concat([body, chunk]))
 
    req.on('end', () => {
 
        if (!isValidRequest(body, WEBHOOK_SECRET, req.headers['x-uipath-signature'])) {
            console.error('Invalid signature')
            resp.statusCode = 401 // Unauthorized
        } else {
 
            let payload = JSON.parse(body.toString('utf8'))
 
            // Process request
            console.log(payload)
 
            resp.statusCode = 202 // Accepted
        }
 
        resp.end()
    })
 
})
 
server.listen(PORT)const { createServer } = require('http');
const { createHmac } = require('crypto');
 
const PORT = 9090
const WEBHOOK_SECRET = '<same secret as configured in Orchestrator>'
 
const isValidRequest = (body /* Buffer */, secret /* string */, expectedSignature /* string */) =>
    expectedSignature == null || createHmac('sha256', secret)
        .update(body)
        .digest('base64') === expectedSignature
 
const server = createServer((req, resp) => {
 
    let body = new Buffer([])
 
    req.on('data', chunk => body = Buffer.concat([body, chunk]))
 
    req.on('end', () => {
 
        if (!isValidRequest(body, WEBHOOK_SECRET, req.headers['x-uipath-signature'])) {
            console.error('Invalid signature')
            resp.statusCode = 401 // Unauthorized
        } else {
 
            let payload = JSON.parse(body.toString('utf8'))
 
            // Process request
            console.log(payload)
 
            resp.statusCode = 202 // Accepted
        }
 
        resp.end()
    })
 
})
 
server.listen(PORT)
  • Common Payload Properties
  • Permissions
  • Authentication
  • Signature Validation Examples

Was this page helpful?

Get The Help You Need
Learning RPA - Automation Courses
UiPath Community Forum
Uipath Logo White
Trust and Security
© 2005-2024 UiPath. All rights reserved.