Skip to main content

Trigger Your RPA App with a Webhook

Webhooks are used to launch apps based on the occurrence of an external event.

Sophie avatar
Written by Sophie
Updated over 3 weeks ago

Webhooks offer a lightweight, real-time way to trigger Octoparse AI apps directly from your own system. By sending an HTTP POST request to a unique webhook URL, you can start an app remotely, pass in input variables, and even specify which bot should run the task. This makes it easy to integrate automation into your internal systems, such as CRMs, ERPs, or other backend services.

Each webhook trigger is associated with a specific app. Once configured, it allows external systems to initiate that app’s execution with just a single API call.

Setting Up a Webhook Trigger

To use a webhook, you’ll first need to create a webhook trigger for the app you want to run. This is done under the Triggers section of your app configuration. Click + New Trigger button, choose the Webhook option and follow the setup steps.

Go to webhook trigger setting
Set the name of your webhook, and select a bot to run your app

Once completed, you’ll be given a unique webhook URL. If needed, you can also enable signature verification for added security, which will require your system to sign each request.

Copy webhook address and signature to integrate Octoparse AI with your system

Be sure to enable the trigger after setup. The webhook will not work until it’s explicitly activated.

Generating the Signature

If you’ve enabled signature verification, each request must include a valid sign field. This signature helps ensure that only authorized systems can trigger the app.

To generate the signature, concatenate the timestamp and your secret key with a newline in between, like this: timestamp + "\n" + secretKey Then, hash the string using the HmacSHA256 algorithm and encode the result in Base64. The resulting string is what you’ll place in the sign field of your request body.

Making a Webhook Request

Once you’ve obtained the webhook URL, you can send a POST request to it using JSON format. The request body can include a timestamp, an optional security signature, and a set of custom parameters for the app.

Here’s what a typical request body looks like:

{ 
"sign": "Base64-encoded HMAC-SHA256 signature",
"params": {
"CustomVar1": "value1",
"CustomVar2": "value2"
},
"timestamp": "Unix timestamp in seconds"
}

The timestamp is required and should be the current Unix timestamp (in seconds). If signature verification is enabled in webhook setting, the sign field must contain a valid signature. The params object includes key-value pairs matching your app’s custom variables.

Request Frequency Limits

Webhook triggers are subject to rate limits to protect system stability. You can send up to 5 requests per second, with a maximum of 20 requests per minute. If these limits are exceeded, the server will return an error response indicating that the rate limit has been hit. To maintain performance, make sure your calling system implements appropriate retry or throttling logic.

Sample Implementation

Below are examples of how to trigger an app using Python, C#, and Java, showing how to construct the request body, generate the signature, and handle the response.

Python

import requests
import json
import hashlib
import hmac
import base64
import time

key = "your_secret_key"
url = "your_webhook_url"

payload = {
"InputVariable1": "value1",
"InputVariable2": "value2"
}
timestamp = str(int(time.time()))
def get_sign(secret, timestamp):
string_to_sign = timestamp + "\n" + secret
sign_data = hmac.new(string_to_sign.encode(), None, hashlib.sha256).digest()
return base64.b64encode(sign_data).decode()

rpa_webhook = {
"timestamp": timestamp,
"sign": get_sign(key, timestamp),
"params": payload,
}

try:
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(rpa_webhook), headers=headers)

if response.status_code == 200:
print("Webhook triggered successfully.")
else: res = response.json()
print("Failed to trigger the webhook.")
print(f"Error description: {res.get('description', 'No description provided')}")
print(f"Error code: {res.get('code', 'No error code')}")
except Exception as ex:
print(f"An exception occurred: {ex}")
raise

C# (.NET 6+)

using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using WebhookDemo.Dtos;
var key = "your_secret_key";
var url = "your_webhook_url";
using var client = new HttpClient();
try
{
var @params = new Dictionary<string, object>
{
{ "InputVariable1", "Value1" },
{ "InputVariable2", "Value2" }
};
var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
var rpaWebhook = new RpaWebhookDto(
timestamp.ToString(),
GetSign(key, timestamp),
@params);
var result = await client.PostAsync(url,
new StringContent(JsonSerializer.Serialize(rpaWebhook), Encoding.UTF8, "application/json"));
if (result.IsSuccessStatusCode)
{
Console.WriteLine("Webhook triggered successfully.");
return;
}
var res = JsonSerializer.Deserialize<WebhookInvokeFailureDto>(
await result.Content.ReadAsStringAsync(),
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
);
Console.WriteLine("Failed to trigger the webhook.");
Console.WriteLine($"Error description:{res!.Description}");
Console.WriteLine($"Error Code:{res!.Code}");
}
catch (Exception ex)
{
Console.WriteLine($"Exception:{ex.Message}");
throw;
}
static string GetSign(string secret, long timestamp)
{
string stringToSign = timestamp + "\n" + secret;
using HMACSHA256 hmac = new(Encoding.UTF8.GetBytes(stringToSign));
byte[] signData = hmac.ComputeHash(Array.Empty<byte>());
return Convert.ToBase64String(signData);
}
namespace WebhookDemo.Dtos
{
public sealed record RpaWebhookDto(
string Timestamp,
string Sign,
Dictionary<string, object>? Params
);
public sealed record WebhookInvokeFailureDto(
string Code,
string Description,
string? RequestId
);
}

Java

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Instant;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

import com.google.gson.Gson;

public class Main {
static HttpClient client = HttpClient.newHttpClient();

public static void main(String[] args) throws NoSuchAlgorithmException, IOException, InterruptedException {
String key = "your_secret_key";
String url = "your_webhook_url";

long timestamp = Instant.now().getEpochSecond();
String sign = getSign(key, timestamp);

Map<String, Object> params = new HashMap<>();
params.put("InpoutVariable1", "Value1");
params.put("InpoutVariable2", "Value2");

RpaWebhookDto rpaWebhook = new RpaWebhookDto(Long.toString(timestamp), sign, params);

String requestBody = new Gson().toJson(rpaWebhook);

HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

if (response.statusCode() == 200) {
System.out.println("Webhook triggered successfully.");
return;
}

WebhookInvokeFailureDto res = new Gson().fromJson(response.body(), WebhookInvokeFailureDto.class);
System.out.println("Failed to trigger the webhook.");
System.out.println("Error description:" + res.getDescription());
System.out.println("Error code:" + res.getCode());
}

static String getSign(String secret, long timestamp) {
String stringToSign = timestamp + "\n" + secret;
try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(stringToSign.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
mac.init(secretKeySpec);
byte[] result = mac.doFinal();
return Base64.getEncoder().encodeToString(result);
} catch (Exception e) {
throw new RuntimeException("getSign error", e);
}
}

static class RpaWebhookDto {
String Timestamp;
String Sign;
Map<String, Object> Params;

public RpaWebhookDto(String timestamp, String sign, Map<String, Object> params) {
Timestamp = timestamp;
Sign = sign;
Params = params;
}
}

static class WebhookInvokeFailureDto {
String Code;
String Description;
String RequestId;
}
}

Common Issues and Troubleshooting

If your webhook request fails, start by confirming that the trigger is enabled and the webhook URL is correct. For signed requests, check that the sign value is generated using the correct secret and timestamp format. Errors such as 400 or 500 responses often indicate a missing or malformed field in the request body.

If you see an error code and message in the response, they will typically point you to the exact cause. Logging both the request payload and response body on your end can help diagnose any issues more quickly.

Learn More

For additional details on working with triggers and bots, see the following resource:

Did this answer your question?