Gareth Wilson Gareth Wilson

Guide to Rocketlane Webhooks: Features and Best Practices

Published


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

FeatureDetails
ConfigurationProfile Icon > Settings > Webhooks > Add Webhook
TriggerAn automation's Send webhook action, on task triggers
URLHTTPS only
Method and formatPOST, JSON
AuthenticationOptional HTTP Basic auth (username and password)
Signature and timestampNone
Success200 or 204
Timeout10 seconds
OrderingNot guaranteed
DuplicatesRocketlane says it guarantees exactly one delivery per event
Retries, source IPsNot 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:

eventTypeResource
TASK_CREATED, TASK_UPDATED, TASK_DELETEDTask
PROJECT_CREATED, PROJECT_UPDATED, PROJECT_ARCHIVED, PROJECT_DELETEDProject
PHASE_CREATED, PHASE_UPDATED, PHASE_DELETEDPhase

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:

  • eventId identifies the event. Rocketlane asks you to quote it to support.
  • data.task follows the shape of Rocketlane's Task API response.
  • changeLog appears only on _UPDATED events. changedFields names what changed, and from and to hold the old and new values.
  • source.actor is the user who made the change, and source.webhook names the webhook that sent it.
  • eventOccurredAt is when the change happened and eventTriggeredAt is 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.

  1. In Rocketlane, click your Profile Icon > Settings, then Webhooks, then Add Webhook.
  2. Enter a Webhook Name and your HTTPS Webhook URL.
  3. Choose Basic authentication and enter the username and password.
  4. Save the webhook.
  5. Go to Automations and create an automation with a task trigger.
  6. Choose the trigger event, and add conditions if you need them.
  7. Click Add an action, choose Send webhook, and select your webhook. Rocketlane shows a sample payload.
  8. 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 201 or 202: 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 eventOccurredAt with 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.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.