Skip to main content

AssetPilot Connect webhook signatures and retries

AssetPilot Connect sends signed events from AssetPilot for Jira to configured webhook endpoints. Use the request headers and raw body to verify each delivery before processing it.

Pre-release

AssetPilot Connect is not on Atlassian Marketplace yet. It requires AssetPilot's app REST API, which is not in production. This page describes the release candidate.

Two webhooks, one failing with HTTP 500, and the built-in signature snippets.

Add a webhook​

  1. Open Webhooks and select Add webhook.
  2. Enter a name and the URL of your receiver.
  3. Choose events: selected events or All events.
  4. Select Save. The signing secret appears once. Copy it into your receiver's configuration, then select I've copied it.
  5. Select Send test. A healthy receiver shows Test event delivered with the HTTP status and time.

Use ⋯ on a row to Edit, Rotate secret or Delete a webhook.

Events​

asset.created, asset.updated, asset.deleted, asset.status_changed, asset.checked_out, asset.checked_in, asset.issue_linked, asset.issue_unlinked, asset.imported, asset.merged, stock.adjusted, reservation.changed, maintenance.changed and custody.changed. Subscribe to selected events or all events (*).

Request​

Every delivery is an HTTPS POST with a JSON body and these headers:

HeaderValue
X-AssetPilot-EventThe event type, for example asset.created
X-AssetPilot-DeliveryA unique delivery id. Use it to ignore duplicates.
X-AssetPilot-Signaturet=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<raw body>" with your webhook secret>

The body looks like this:

FieldContents
idEvent id
typeEvent type, for example asset.checked_out
occurredAtISO 8601 timestamp
site{ url, cloudId } of your Jira site
dataThe AssetPilot event: asset id and tag, kind, the actor's Atlassian account id, a summary and the changes
From AssetPilot event to a verified delivery.

Verify the signature​

Check every request against the raw body before parsing it. Reject the request if the signature does not match or t is more than 300 seconds away from your clock.

Node.js

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyAssetPilotSignature(secret, header, rawBody, now = Math.floor(Date.now() / 1000)) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const t = Number(parts.t);
if (!Number.isFinite(t) || Math.abs(now - t) > 300) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`, 'utf8').digest('hex');
const given = Buffer.from(parts.v1 ?? '', 'hex');
const want = Buffer.from(expected, 'hex');
return given.length === want.length && timingSafeEqual(given, want);
}

Python

import hashlib
import hmac
import time


def verify_assetpilot_signature(secret: str, header: str, raw_body: bytes, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(",") if "=" in p)
try:
t = int(parts["t"])
except (KeyError, ValueError):
return False
if abs(time.time() - t) > tolerance:
return False
signed = f"{t}.".encode() + raw_body
expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))

The secret is shown once when you create the webhook. You can rotate it at any time.

Use the raw body

Frameworks often parse JSON before your handler runs. Read the body as raw bytes, for example with express.raw({ type: 'application/json' }), verify it, then parse.

Retries and redelivery​

Connect retries a network error or any non-2xx response up to 6 times with backoff, over about 9 hours.

The last 500 deliveries appear in Activity. You can redeliver any of them.

Return a 2xx quickly and do slow work afterwards. Use X-AssetPilot-Delivery to ignore a delivery you already processed.

Rotate the secret​

Select ⋯ → Rotate secret and confirm. The current secret stops working immediately, and the new secret is shown once. Update your receiver straight away.

Allowed URLs​

Webhook URLs must use https and must not point to private, loopback or link-local addresses.

Review Data and privacy for payload data and delivery log retention.