Guide to Workato Webhooks: Features and Best Practices
Workato is an enterprise automation platform. Teams build recipes that react to events in hundreds of business apps, such as a new Salesforce opportunity, a NetSuite order or a scheduled timer, and then act on other apps. When one of those actions needs to reach your own application, the recipe calls it over HTTP, which makes Workato a webhook sender you design yourself.
This guide covers how the HTTP connector sends requests, how to shape them so one endpoint can serve several recipes, how to authenticate them with HTTP Basic credentials, how Workato handles timeouts, errors and retries, and the practices that keep a receiver reliable in production.
What are Workato webhooks?
Workato has no outbound webhook feature with fixed events. Instead, a recipe step uses the HTTP connector's Send request via HTTP action. The request goes through an HTTP connection, which holds the authentication settings and a Base URL, and the action adds the method, path, parameters, headers and body.
That means the method, body and any event name are all chosen by whoever builds the recipe. Workato's own webhook triggers, where other services call into a recipe, are the opposite direction and are not covered here.
Workato does not sign requests. The HTTP connection supports many authentication types, and Basic is the one Hookdeck's Workato source checks.
Workato webhook features
| Feature | Details |
|---|---|
| Mechanism | Send request via HTTP action in a recipe, using an HTTP connection |
| Base URL | Set on the connection. Recipes can't override it, and the action adds a relative path |
| Method | The recipe author's choice, such as POST, PUT, PATCH, GET or DELETE |
| Body | The recipe author's choice of request content type, such as JSON or raw JSON |
| Event types | None built in. Add your own event field |
| Authentication | None, Basic, Header auth, Query params, Custom, OAuth 2, AWS and Azure options. No signature |
| Timeout | Up to 120 seconds, or 11 to 3600 seconds with Wait for response |
| Errors | Non-2xx responses fail the step and stop the job unless handled |
| Retries | Implicit retry on timeouts for GET, HEAD, PUT and DELETE, unless Disable retries is set |
Events
Because there are no built-in event types, the body is whatever the recipe builds. If several recipes call the same endpoint, agree on a small envelope so your handler can route and deduplicate:
{
"event": "order.created",
"id": "a1b2c3d4-job-or-record-id",
"data": {
"order_id": "ord_123",
"email": "jane@example.com"
}
}
| Field | Purpose |
|---|---|
event | A name you choose, such as order.created or record.updated, used for routing |
id | A unique value from the recipe, such as the record ID plus its updated time, used for deduplication |
data | The fields mapped from earlier recipe steps |
In the action, set Request content type to a JSON option. JSON request body builds input fields from a sample JSON object, and Raw JSON request body lets you type the structure directly.
Inspect Workato webhooks as they arrive. Set a Hookdeck Inspect URL as the connection's Base URL and run the recipe step to see the exact method, headers and body Workato sends, with no account or setup required.
Setting up Workato webhooks
Pick a username and generate a long random password, for example with openssl rand -hex 32, and store both on your receiver.
- In Workato, create a connection for the HTTP connector and give it a name.
- Set Authentication type to Basic.
- Enter the username in Basic auth user and the password in Basic auth password.
- Enter your HTTPS endpoint in Base URL, then connect.
- In your recipe, add the Send request via HTTP action using that connection.
- Choose the Method, a relative Request URL such as
webhooks/workato, and a JSON request content type, then map the body. - Test the step and check that your endpoint receives the request.
The credentials must arrive on the first request. Workato's documentation says Basic credentials are Base64-encoded in transit, but doesn't say whether they are sent straight away or only after a 401 challenge with a WWW-Authenticate header. A sender that waits for a challenge will never authenticate against a receiver that doesn't issue one, so check the first test request for an Authorization header.
To put Hookdeck in front of your service, create a Hookdeck source with the Workato type and use its URL as the connection's Base URL. Enter the same Username and Password on the source. Hookdeck does not send a 401 challenge, so it needs the credentials on the first request. Hookdeck still answers with a 200, but a request with missing or wrong credentials is recorded as failed verification and never reaches your destination. The source has POST selected. If your recipe uses PUT, PATCH, GET or DELETE, allow that method on the Hookdeck source as well.
If the recipe uses the response, for example to read an ID your service returns in a later step, don't put Hookdeck in between: Workato would receive Hookdeck's acknowledgement, not your service's response. Hookdeck fits steps that only need to know the request was accepted.
Securing Workato webhooks
With Basic authentication, each request carries Authorization: Basic base64(username:password). Decode it, split on the first colon, and compare the username and password with your stored values in constant time.
const crypto = require('crypto');
const express = require('express');
function safeEqual(a, b) {
// timingSafeEqual throws on unequal lengths, so check first.
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
function verifyBasicAuth(header, username, password) {
if (!username || !password) return false; // never accept when unconfigured
const match = /^basic\s+([A-Za-z0-9+/]+={0,2})\s*$/i.exec(header || '');
if (!match) return false;
const decoded = Buffer.from(match[1], 'base64');
const colon = decoded.indexOf(0x3a); // split on the first colon: passwords may contain ':'
if (colon === -1) return false;
const userOk = safeEqual(decoded.subarray(0, colon), Buffer.from(username, 'utf8'));
const passOk = safeEqual(decoded.subarray(colon + 1), Buffer.from(password, 'utf8'));
return userOk && passOk; // evaluate both before deciding
}
const app = express();
// The method is the recipe's choice, so accept any.
app.all('/webhooks/workato', express.raw({ type: '*/*' }), (req, res) => {
const ok = verifyBasicAuth(
req.get('authorization'),
process.env.WORKATO_WEBHOOK_USERNAME,
process.env.WORKATO_WEBHOOK_PASSWORD
);
if (!ok) return res.sendStatus(401);
let payload = {};
if (req.body && req.body.length > 0) { // a GET has no body
try {
payload = JSON.parse(req.body.toString('utf8'));
} catch {
return res.sendStatus(400);
}
}
// Skip payload.id if you have seen it, then route on payload.event.
switch (payload.event) {
case 'order.created':
case 'record.updated':
break;
default:
// Log and acknowledge anything else.
}
res.sendStatus(200);
});
The same check in Python:
import base64
import binascii
import hmac
import os
import re
BASIC_PATTERN = re.compile(r"^basic\s+([A-Za-z0-9+/]+={0,2})\s*$", re.IGNORECASE)
def verify_basic_auth(header, username, password) -> bool:
if not username or not password:
return False # never accept when unconfigured
match = BASIC_PATTERN.match(header or "")
if not match:
return False
try:
decoded = base64.b64decode(match.group(1), validate=True)
except (binascii.Error, ValueError):
return False
received_user, sep, received_password = decoded.partition(b":") # first colon only
if not sep:
return False
# Compare bytes: compare_digest raises TypeError on a non-ASCII str.
user_ok = hmac.compare_digest(received_user, username.encode("utf-8"))
password_ok = hmac.compare_digest(received_password, password.encode("utf-8"))
return user_ok and password_ok
# verify_basic_auth(request.headers.get("authorization"),
# os.environ.get("WORKATO_WEBHOOK_USERNAME"),
# os.environ.get("WORKATO_WEBHOOK_PASSWORD"))
Basic credentials prove the sender knows the password. They do not cover the body and carry no timestamp, so a modified or replayed request still passes. Use an HTTPS Base URL, a long random password, and rotate it on the connection if it might have leaked. Anyone who can edit the recipe or connection controls what is sent, so limit who has that access in Workato.
The HTTP connection's Header auth type, which sends a custom header such as a bearer token, is another option, but Hookdeck's Workato source checks Basic credentials only. To use a header token through Hookdeck, use a generic source with API key authentication instead.
Make Workato webhooks production-ready. Hookdeck Event Gateway checks the Basic credentials, acknowledges Workato straight away, and delivers each request to your service with retries you control.
Workato webhook limitations and pain points
Credentials have to arrive without a challenge
The Problem: Every request fails authentication even though the credentials are right.
Why It Happens: Some HTTP clients only send Basic credentials after a server answers 401 with a WWW-Authenticate challenge. Workato's docs don't say which way the HTTP connector works, and a receiver that verifies the request as it arrives, as Hookdeck does, never issues that challenge.
Workarounds:
- Test the step against a Hookdeck Inspect URL first and check that the
Authorizationheader is there. - If it isn't, use a header token with a source that checks it.
How Hookdeck Can Help: Hookdeck keeps every request, including those that fail verification, with full headers, so you can see straight away whether Authorization arrived.
A failed request stops the job
The Problem: A short outage or slow deploy on your side fails Workato jobs, and someone has to rerun them.
Why It Happens: The HTTP connector treats non-2xx responses as errors, which stop the job unless the step is set to Mark non-2xx response codes as success or a Handle errors step catches them. Implicit retries only cover timeouts on GET, HEAD, PUT and DELETE, so a failed POST isn't retried.
Workarounds:
- Wrap the step in a Handle errors block with retries.
- Keep your endpoint fast, and acknowledge before slow work.
How Hookdeck Can Help: Hookdeck acknowledges the request as soon as it arrives and stores it, so the Workato job finishes. Delivery to your service then uses retries you configure, and issues alert you when deliveries fail.
Retries can send the same request twice
The Problem: One recipe run creates two records in your system.
Why It Happens: Implicit retries on timeouts, Handle errors retries and manual job reruns all resend the request, and a timeout doesn't mean your service didn't process it.
Workarounds:
- Send a unique
idin the body and deduplicate on it. - Set Disable retries on steps that must never repeat, and handle failures explicitly.
How Hookdeck Can Help: Hookdeck deduplication can drop repeats based on a body field such as id before they reach your service.
No standard payload
The Problem: Each recipe sends a different shape, and your handler grows a branch per recipe.
Why It Happens: Workato has no built-in events, so every recipe author designs their own body.
Workarounds:
- Agree on the
event,idanddataenvelope and use it in every recipe. - Or give each recipe its own path under the Base URL.
How Hookdeck Can Help: Transformations can reshape requests from older recipes into your standard envelope, and filters can route by event or path to different connections.
Best practices
Use one envelope for every recipe
event, id and data in every body make routing, logging and deduplication the same for all recipes. See our guide to webhook idempotency.
Use POST for notifications
Sending events with POST keeps them out of URL logs and means a body is always present. If a recipe uses another method, accept it on your endpoint and on the Hookdeck source.
Keep the response small and fast
Return 200 quickly once the request is authenticated and process it from a queue. Workato waits for your response and fails the step on a timeout. See why to process webhooks asynchronously.
Limit who can change the connection
The connection holds the credentials and the Base URL. Restrict edit access to it, and rotate the password when people with access leave.
Conclusion
Workato sends webhooks through the HTTP connector, so the method, body and event names are yours to design. Use Basic credentials over HTTPS that arrive on the first request, compare them in constant time, send an event and id in a common envelope, and deduplicate because retries and reruns can repeat a request.
Hookdeck Event Gateway checks the Basic credentials, acknowledges Workato immediately, and delivers each request to your service with retries and deduplication.
Get started with Hookdeck for free and handle Workato webhooks reliably in minutes.