Agent skill
Rocketlane Webhooks Skill
Receive and authenticate Rocketlane customer onboarding webhooks. Use when setting up a Rocketlane webhook endpoint, checking HTTP Basic authentication (username and password), debugging 401s, or handling events such as TASK_CREATED, TASK_UPDATED, PROJECT_CREATED and PHASE_UPDATED.
Install this skill
npx skills add hookdeck/webhook-skills --skill rocketlane-webhooks
Rocketlane (customer onboarding and project delivery) sends a POST with a JSON body to a webhook you define in Settings > Webhooks. A Send webhook action in an automation fires it. Payloads are not signed. The only authentication Rocketlane offers is HTTP Basic auth, which the docs call optional but recommended.
In Hookdeck: choose the Rocketlane source type. Choose Basic authentication and set a username and password on the Rocketlane webhook.
When to Use This Skill
- How do I receive Rocketlane webhooks?
- How do I verify a Rocketlane webhook? (Basic auth, there is no signature)
- Why does my Rocketlane webhook endpoint return 401?
- How do I handle
TASK_CREATED,TASK_UPDATEDorPROJECT_CREATEDevents? - Why does Rocketlane show my webhook delivery as failed?
Verification (core)
Rocketlane sends Authorization: Basic base64(username:password) using the credentials you entered on the webhook. Parse it strictly, split on the first colon, and compare the username and the password each in constant time. Evaluate both before deciding:
const crypto = require('crypto');
// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
const safeEqual = (a, b) =>
crypto.timingSafeEqual(
crypto.createHash('sha256').update(a).digest(),
crypto.createHash('sha256').update(b).digest());
function verifyRocketlane(authorization, user = process.env.ROCKETLANE_WEBHOOK_USERNAME,
pass = process.env.ROCKETLANE_WEBHOOK_PASSWORD) {
if (!user || !pass) return false; // never accept when unconfigured
const m = /^basic[ \t]+([A-Za-z0-9+/]+={0,2})$/i.exec((authorization || '').trim());
if (!m || m[1].length % 4) return false; // strict base64 only
const bytes = Buffer.from(m[1], 'base64');
if (bytes.toString('base64') !== m[1]) return false; // non-canonical padding/bits
let decoded;
try {
decoded = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
} catch {
return false; // not valid UTF-8
}
const i = decoded.indexOf(':'); // first colon
if (i < 0) return false;
const userOk = safeEqual(decoded.slice(0, i), user);
const passOk = safeEqual(decoded.slice(i + 1), pass); // no short-circuit
return userOk && passOk;
}
Return 401 when this fails, 400 for a body that isn't a JSON object, and 200 once handled. Express must read the body raw (express.raw({ type: '*/*' })) and parse it only after the check. In Python use base64.b64decode(token, validate=True) and hmac.compare_digest on bytes (a str with non-ASCII characters raises). Full Python and Next.js versions are in references/verification.md.
Know what this does and does not prove. A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use HTTPS only, and rotate the username and password if they leak. Dedupe on eventId.
Credentials must arrive on the first request. The docs don't say whether Rocketlane sends Basic credentials preemptively, and Hookdeck never answers with a 401 plus WWW-Authenticate challenge: it verifies the request as received.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Event Types
The body has eventType and resourceType. These eventType values come from Rocketlane's Event Payload page:
eventType | Fires when |
|---|---|
TASK_CREATED | A task is created |
TASK_UPDATED | A task changes (adds changeLog with changedFields, from, to) |
TASK_DELETED | A task is deleted |
PROJECT_CREATED, PROJECT_UPDATED, PROJECT_ARCHIVED, PROJECT_DELETED | Project lifecycle |
PHASE_CREATED, PHASE_UPDATED, PHASE_DELETED | Phase lifecycle |
The docs' payload-structure snippet prints "TASK_UPDATED." with a stray full stop; the real sample payloads have none, and the examples match the plain strings. Rocketlane lists only TASK as a supported resourceType and says only task triggers are supported for webhooks automations today, so expect task events first.
Delivery Rules
- Only
200or204count as delivered. Any other status, or no response in 10 seconds, is a failure. - Order is not guaranteed to be chronological. The docs say Rocketlane delivers each event exactly once.
Environment Variables
ROCKETLANE_WEBHOOK_USERNAME=rocketlane # as entered on the Rocketlane webhook
ROCKETLANE_WEBHOOK_PASSWORD=replace-with-a-long-random-password
Local Development
npx hookdeck-cli listen 3000 rocketlane --path /webhooks/rocketlane
No account required. Paste the printed URL as the webhook URL in Rocketlane (HTTPS only).
Resources
- references/overview.md - Payload fields and event types
- references/setup.md - Creating the webhook and automation in Rocketlane
- references/verification.md - Basic auth check in Node, Python and Next.js, gotchas
- examples/ - Runnable Express, Next.js and FastAPI handlers with tests