Guide to Rocketlane Webhooks: Features and Best Practices
Rocketlane webhooks send customer onboarding and project delivery activity to your own systems. When a task is created, updated or deleted in a Rocketlane project, an automation can send the change to your service, so you can update a CRM, alert an account team or keep a reporting database current.
This guide covers how Rocketlane webhooks and automations fit together, how to authenticate requests with Basic auth, what the payload contains, and the practices that make a Rocketlane receiver dependable.
What are Rocketlane webhooks?
In Rocketlane, a webhook is a saved destination: a name, an HTTPS URL and optional credentials. On its own it sends nothing. You fire it from an automation: pick a trigger event, optionally add conditions, then add a Send webhook action that names the webhook. Rocketlane notes that "currently, we only support task triggers for webhooks".
Each delivery is an HTTP POST with a JSON envelope describing the event, the task, what changed and who changed it.
Rocketlane doesn't sign webhook requests. The only authentication it offers is HTTP Basic auth: "Only Basic Authentication is supported currently." It's optional, but Rocketlane recommends it, and it's the only way to tell a real request from a forged one.
Rocketlane webhook features
| Feature | Details |
|---|---|
| Configuration | Profile Icon > Settings > Webhooks > Add Webhook |
| Trigger | An automation's Send webhook action, on task triggers |
| URL | HTTPS only |
| Method and format | POST, JSON |
| Authentication | Optional HTTP Basic auth (username and password) |
| Signature and timestamp | None |
| Success | 200 or 204 |
| Timeout | 10 seconds |
| Ordering | Not guaranteed |
| Duplicates | Rocketlane says it guarantees exactly one delivery per event |
| Retries, source IPs | Not documented |
Events and payloads
The automation's trigger decides when the webhook fires, and the payload's eventType says what happened. Rocketlane's payload docs list these values:
eventType | Resource |
|---|---|
TASK_CREATED, TASK_UPDATED, TASK_DELETED | Task |
PROJECT_CREATED, PROJECT_UPDATED, PROJECT_ARCHIVED, PROJECT_DELETED | Project |
PHASE_CREATED, PHASE_UPDATED, PHASE_DELETED | Phase |
The same page lists TASK as the only supported resourceType, and the setup docs say only task triggers are supported, so expect task events in practice and handle anything else as unknown. The payload docs' structure example prints "TASK_UPDATED." with a stray full stop. The sample payloads don't have it, so match the plain value.
This is a trimmed version of Rocketlane's TASK_UPDATED sample:
{
"eventId": "a3c7825b-9c89-42ac-8859-50e243d0c131",
"resourceType": "TASK",
"eventType": "TASK_UPDATED",
"version": "1.0",
"data": {
"task": {
"taskId": 318,
"taskName": "Hire Chief Operating Officer",
"project": { "projectId": 110, "projectName": "Hamlin, Hamlin & McGill" },
"phase": { "phaseId": 115, "phaseName": "Hire for different roles" },
"status": { "value": 3, "label": "Completed" }
}
},
"changeLog": {
"changedFields": ["taskName"],
"from": { "taskName": "Hire operations head" },
"to": { "taskName": "Hire Chief Operating Officer" }
},
"source": {
"webhook": { "webhookId": 1, "webhookName": "Receive Rocketlane Notification" },
"actor": {
"emailId": "bobo@rocketlane.com",
"userId": 1,
"firstName": "Bob",
"lastName": "Odenkrik"
}
},
"eventOccurredAt": 1704199907693,
"eventTriggeredAt": 1704199908692
}
The fields to know:
eventIdidentifies the event. Rocketlane asks you to quote it to support.data.taskfollows the shape of Rocketlane's Task API response.changeLogappears only on_UPDATEDevents.changedFieldsnames what changed, andfromandtohold the old and new values.source.actoris the user who made the change, andsource.webhooknames the webhook that sent it.eventOccurredAtis when the change happened andeventTriggeredAtis when Rocketlane sent it, both in epoch milliseconds.
Inspect Rocketlane webhooks as they arrive. Point a webhook at a Hookdeck Inspect URL and test the automation to see the exact headers and body, with no account or setup required.
Setting up Rocketlane webhooks
Choose a username and a long random password first, for example with openssl rand -hex 32.
- In Rocketlane, click your Profile Icon > Settings, then Webhooks, then Add Webhook.
- Enter a Webhook Name and your HTTPS Webhook URL.
- Choose Basic authentication and enter the username and password.
- Save the webhook.
- Go to Automations and create an automation with a task trigger.
- Choose the trigger event, and add conditions if you need them.
- Click Add an action, choose Send webhook, and select your webhook. Rocketlane shows a sample payload.
- Save, then test the automation.
To route through Hookdeck, create a source with the Rocketlane type and use its URL as the webhook URL. Enter the same values in the source's Username and Password fields. The source accepts POST. Hookdeck never answers with a 401 challenge, so the credentials must arrive with each request. Rocketlane's docs don't say whether it sends them up front, so send a test from the automation and confirm it passes before you rely on it.
Securing Rocketlane webhooks
Decode the Authorization: Basic header, split on the first colon (a password can contain colons), and compare the username and password with your stored values in constant time.
const crypto = require('crypto');
const express = require('express');
const USERNAME = process.env.ROCKETLANE_WEBHOOK_USERNAME;
const PASSWORD = process.env.ROCKETLANE_WEBHOOK_PASSWORD;
function safeEqual(a, b) {
// timingSafeEqual throws on unequal lengths, so check first.
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
function verifyBasicAuth(header) {
if (!USERNAME || !PASSWORD || typeof header !== 'string') return false;
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
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;
}
const app = express();
app.post('/webhooks/rocketlane', express.raw({ type: '*/*' }), (req, res) => {
if (!verifyBasicAuth(req.get('authorization'))) {
return res.sendStatus(401);
}
let event;
try {
event = JSON.parse(req.body.toString('utf8'));
} catch {
return res.sendStatus(400);
}
// Queue the event keyed on event.eventId, then respond within 10 seconds.
res.sendStatus(200);
});
The same check in Python:
import base64
import binascii
import hmac
import os
USERNAME = os.environ.get("ROCKETLANE_WEBHOOK_USERNAME", "")
PASSWORD = os.environ.get("ROCKETLANE_WEBHOOK_PASSWORD", "")
def verify_basic_auth(header) -> bool:
if not USERNAME or not PASSWORD or not header:
return False
scheme, _, encoded = header.partition(" ")
if scheme.lower() != "basic":
return False
try:
decoded = base64.b64decode(encoded.strip(), validate=True)
except (binascii.Error, ValueError):
return False
user, sep, password = decoded.partition(b":")
if not sep:
return False
user_ok = hmac.compare_digest(user, USERNAME.encode("utf-8"))
pass_ok = hmac.compare_digest(password, PASSWORD.encode("utf-8"))
return user_ok and pass_ok
Basic credentials are static. They authenticate the sender, not the body, so a modified payload still passes, and with no signed timestamp a captured request can be replayed. Serve the endpoint over HTTPS only, use a long random password, and change it on the webhook and in your environment together if it might have leaked.
Make Rocketlane webhooks production-ready. Hookdeck Event Gateway checks the Basic credentials on every Rocketlane event, stores each one durably, and lets you replay any delivery after a fix.
Rocketlane webhook limitations and pain points
Authentication is optional
The Problem: Requests arrive at your endpoint with nothing to authenticate them.
Why It Happens: Basic auth is an optional step when you add a webhook, and Rocketlane offers no signature.
Workarounds:
- Set Basic auth on every webhook, and fail closed when the header is missing.
- Review existing webhooks under Settings > Webhooks.
How Hookdeck Can Help: Hookdeck's Rocketlane source requires the username and password. Hookdeck answers Rocketlane with a 200 either way, but a request with missing or wrong credentials is recorded as failed verification and never reaches your destination.
A 10-second timeout
The Problem: Rocketlane records a delivery as failed even though your service processed it.
Why It Happens: Rocketlane fails a delivery that gets no response within 10 seconds, or that gets any status other than 200 or 204.
Workarounds:
- Check the credentials, store the event, and respond before doing any work.
- Don't return
201or202: Rocketlane counts them as failures.
How Hookdeck Can Help: Hookdeck responds to Rocketlane as soon as a request arrives, then delivers it to your service with a delivery timeout and retries you configure.
No documented retries
The Problem: You can't tell whether an event that failed during your outage will be sent again.
Why It Happens: Rocketlane documents what counts as failure, and says it delivers each event exactly once, but not whether a failed delivery is retried.
Workarounds:
- Treat a failed delivery as lost, and re-sync affected projects from the Rocketlane API after an outage.
How Hookdeck Can Help: Hookdeck stores every event it receives and holds it while your service is down. Failed deliveries are retried automatically, and you can replay any of them once your service is back.
Out-of-order events
The Problem: An older update overwrites a newer one.
Why It Happens: Rocketlane says delivery order "is not guaranteed to be strictly chronological".
Workarounds:
- Compare
eventOccurredAtwith the time of the last change you applied to the task, and skip older events. - For important fields, re-read the task from the API before writing.
How Hookdeck Can Help: Hookdeck can set a max delivery rate on your destination, which reduces how many events your service handles at once.
Best practices
Deduplicate on eventId
Rocketlane promises one delivery per event, but a replay from Hookdeck or a retry on your side can still repeat one. Store eventId before acting. See our guide to webhook idempotency.
Route on eventType, not the automation
Several automations can send to the same webhook. Route on eventType and use changeLog.changedFields to skip updates you don't care about.
Keep credentials in configuration
Store the username and password as secrets, and update the webhook and your receiver together when you change them.
Acknowledge fast and process asynchronously
With a 10-second limit, verify, store, return 200, and do the work in a worker. See why to process webhooks asynchronously.
Conclusion
Rocketlane webhooks are fired by automations on task triggers and send a JSON envelope with the task, a change log for updates, and the user who acted, authenticated only by optional Basic auth. Turn Basic auth on for every webhook, compare the username and password in constant time, respond with 200 within 10 seconds, and deduplicate and order events using eventId and eventOccurredAt.
Hookdeck Event Gateway sits in front of your receiver, checks the credentials, and keeps every event until your service has processed it.
Get started with Hookdeck for free and handle Rocketlane webhooks reliably in minutes.