Agent skill
Onshape Webhooks Skill
Receive and verify Onshape (PTC cloud CAD) webhooks. Use when setting up an Onshape webhook endpoint, verifying the X-onshape-webhook-signature-primary header (base64 HMAC-SHA256 of timestamp.body), debugging Onshape signature verification failures, or handling events like onshape.model.lifecycle.changed, onshape.model.translation.complete, onshape.document.lifecycle.created, onshape.revision.created and onshape.comment.create.
Install this skill
npx skills add hookdeck/webhook-skills --skill onshape-webhooks
When to Use This Skill
- How do I receive Onshape webhooks?
- How do I verify the Onshape
X-onshape-webhook-signature-primarysignature? - Why is my Onshape webhook signature verification failing?
- How do I handle
onshape.model.lifecycle.changed,onshape.model.translation.completeoronshape.comment.createevents? - How do I register an Onshape webhook (
POST /api/v6/webhooks) and set a signature key?
Verification (core)
Onshape signature keys are an Enterprise company setting. Paste the primary key; only the primary signature is verified.
Apps register webhooks with the REST API (POST /api/v6/webhooks). Company administrators then set signature keys in Company/Classroom/Enterprise settings > Webhooks. Each delivery is an HTTP POST with a JSON body and these headers:
X-onshape-webhook-signature-primary— present when a primary key is set: standard padded base64 HMAC-SHA256, no prefixX-onshape-webhook-timestamp— when the webhook was sent; it is part of the signed contentX-onshape-webhook-signature-secondary— present when a secondary key is set (ignore it: this skill verifies the primary signature only)
Signed content is the timestamp header value exactly as received, a literal ., then the raw request body bytes. The key is the primary signature key used as a UTF-8 string.
const crypto = require('crypto');
function verifyOnshapeSignature(rawBody, timestamp, signature, secret) {
if (!timestamp || !signature || !secret) return false;
if (!/^[A-Za-z0-9+/]{43}=$/.test(signature)) return false; // validate before comparing
const message = Buffer.concat([Buffer.from(timestamp, 'latin1'), Buffer.from('.'), rawBody]);
const expected = crypto.createHmac('sha256', secret).update(message).digest('base64');
const a = Buffer.from(signature);
const b = Buffer.from(expected);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Missing or empty headers, a malformed value or a mismatch: respond 401. In Express use express.raw({ type: '*/*' }); in Next.js await request.arrayBuffer(); in FastAPI await request.body(). Never parse and re-serialize the body before verifying.
Timestamp window: off by default. Hookdeck retries and replays resend the original headers and timestamp, so a fixed window would reject legitimate retries. To opt in, set ONSHAPE_ (unset or 0 = off); the examples then reject deliveries whose X-onshape-webhook-timestamp is older than that.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Common Event Types
Dispatch on the body's event field. Onshape documents more event types in its API Explorer (createWebhook).
| Event | Triggered When |
|---|---|
onshape.model.lifecycle.changed | A model (part studio, assembly) changes |
onshape.model.translation.complete | A translation (import/export) finishes (translationId) |
onshape.document.lifecycle.created | A document is created |
onshape.document.lifecycle.statechange | A document moves to ACTIVE, TRASH or DELETED (documentState) |
onshape.revision.created | A release revision is created |
onshape.comment.create | A comment is created (commentId) |
onshape.user.lifecycle.updateappsettings | A user's app settings change (userId, clientId) |
webhook.register / webhook.ping / webhook.unregister | Sent automatically when a webhook is registered, pinged or removed; just return 200 |
Environment Variables
ONSHAPE_WEBHOOK_SECRET=your_primary_signature_key
# Optional, off when unset or 0
ONSHAPE_WEBHOOK_TOLERANCE_SECONDS=0
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 onshape --path /webhooks/onshape
Reference Materials
- references/overview.md - Onshape webhooks, events, payload fields, delivery
- references/setup.md - Register a webhook and configure signature keys
- references/verification.md - Signature details, gotchas, debugging