Webhooks

Stay informed about important events in your Duro library with real-time webhook notifications.

Webhooks follow a "Ping then Pull" pattern - you receive lightweight event notifications with key metadata, then fetch full resource details using our GraphQL API when needed.

Overview

Duro webhooks let your applications receive real-time notifications when important events occur in your library. Instead of constantly polling for changes, webhooks push event notifications directly to your specified endpoints, helping you build responsive integrations that react immediately to data changes.

Key Benefits

  • Real-time updates - Get notified instantly when data changes

  • Efficient integration - No need for constant API polling

  • Selective subscriptions - Subscribe only to the events you care about

  • Reliable delivery - Built-in retry mechanisms with exponential backoff

  • Secure - HMAC-SHA256 signature verification to ensure authenticity

How Webhooks Work

  1. Event occurs - Something happens in Duro (e.g., a component is updated)

  2. Notification sent - Duro sends a lightweight JSON payload to your webhook URL

  3. Fetch full data - Your application uses the provided metadata to fetch complete details via GraphQL as needed

This pattern keeps webhook payloads small and fast while giving you access to all the data you need.


Available Events

Webhooks are scoped to a specific library. Each webhook can subscribe to one or more event types.

Component Events

These events fire when components in your library are created, updated, or deleted:

GraphQL Enum
Payload Value
Description

COMPONENT_CREATED

components.created

A new component was created in the library

COMPONENT_UPDATED

components.updated

An existing component was modified

COMPONENT_DELETED

components.deleted

A component was removed from the library

When subscribing to events via GraphQL, use the enum name (e.g., COMPONENT_CREATED). When processing webhook payloads, the event field contains the string value (e.g., components.created).

Change Order Events (Coming Soon)

GraphQL Enum
Payload Value
Description

CHANGE_ORDER_OPENED

change_orders.opened

A new change order was created

CHANGE_ORDER_UPDATED

change_orders.updated

Change order details were modified

CHANGE_ORDER_DELETED

change_orders.deleted

A change order was removed

CHANGE_ORDER_STAGE_TRANSITION

change_orders.stage_transition

Change order moved to a different workflow stage

CHANGE_ORDER_STAGE_REVIEWER_DECISION

change_orders.stage_reviewer_decision

A reviewer approved or rejected their stage

CHANGE_ORDER_RESOLUTION

change_orders.resolution

Change order was fully approved, rejected, or withdrawn


Setting Up Webhooks

Create a Webhook

To create a webhook, you'll need:

  • A libraryId - the library you want to monitor

  • A url - your HTTPS endpoint that will receive notifications

  • A list of events - which event types to subscribe to

Configuration Options

Field
Required
Description
Default

libraryId

Yes

UUID of the library to monitor

-

name

Yes

Unique name for this webhook (1-100 characters)

-

url

Yes

HTTPS endpoint URL (must be valid HTTPS)

-

events

Yes

Array of event types to subscribe to

-

description

No

Optional description (max 500 characters)

null

signingSecret

No

Secret for HMAC signature verification (min 16 characters if provided)

null

timeoutSeconds

No

Request timeout in seconds (5-300)

30

maxRetries

No

Maximum retry attempts on failure (0-10)

3

isEnabled

No

Whether the webhook is active

true

isArchived

Read-only

Whether the webhook has been archived (set via archive mutation)

false

List Your Webhooks

Retrieve all webhooks for one or more libraries:

The findAll query only returns active (non-archived) webhooks. Archived webhooks are excluded from results.

Get a Specific Webhook

The findOne query returns a webhook_not_found error if the webhook has been archived.

Update a Webhook

You can update any webhook configuration field:

Add Events to a Webhook

Add additional event subscriptions without removing existing ones:

Remove Events from a Webhook

Remove specific event subscriptions:

Archive a Webhook

When you no longer need a webhook but want to preserve its configuration history, you can archive it instead of deleting it. Archived webhooks:

  • Stop receiving events - No new event deliveries will be attempted

  • Are hidden from queries - Won't appear in findAll or findOne results

  • Free up the name - You can create a new webhook with the same name

  • Cannot be unarchived - This action is permanent

When to Archive vs. Disable

Action
Use Case

Disable (isEnabled: false)

Temporarily pause deliveries; webhook remains queryable and can be re-enabled

Archive

Permanently retire a webhook; frees up the name for reuse


Webhook Payloads

All webhook notifications follow a consistent JSON structure:

Payload Fields Explained

Field
Type
Description

event

string

The event type (e.g., components.created)

eventId

string

Unique identifier for this webhook delivery (UUID)

sourceId

string

Internal event ID for tracking and debugging

timestamp

string

ISO 8601 timestamp when the event occurred

metadata

object

Event-specific data (see below)

Component Event Metadata

For component events, the metadata object contains:

Field
Type
Description

componentId

string

UUID of the affected component

revisionValue

string

Current revision value (e.g., "1.A", "2.B")

version

number

Current version number

Example: Component Created

Example: Component Updated

HTTP Headers

Each webhook request includes these headers:

Header
Value

Content-Type

application/json

User-Agent

Duro-Webhook-Service/1.0

X-Webhook-Signature

HMAC-SHA256 signature (only if signingSecret is configured)


Security

Webhook Signatures

If you configure a signingSecret for your webhook, each request will include an X-Webhook-Signature header containing an HMAC-SHA256 signature of the payload. Always verify this signature to ensure the request came from Duro.

Verifying Signatures (Node.js)

Verifying Signatures (Python)

Security Best Practices

  • Always use HTTPS - Webhook URLs must use HTTPS (enforced by Duro)

  • Verify signatures - Always validate the X-Webhook-Signature header

  • Use timing-safe comparison - Prevent timing attacks when comparing signatures

  • Keep secrets secure - Store your signingSecret in environment variables, never in code

  • Rotate secrets periodically - Update your signing secret regularly


Fetching Full Resource Data

After receiving a webhook notification, use the provided IDs to fetch complete resource details via GraphQL.

Fetch Component Details

Example: Complete Webhook Handler

Here's a complete example showing how to receive a webhook and fetch the full component data:


Retry Logic & Error Handling

Duro automatically retries failed webhook deliveries using exponential backoff.

Retry Schedule

When a webhook delivery fails, Duro will retry with the following delays:

Attempt
Delay After Failure

1st retry

1 second

2nd retry

2 seconds

3rd retry

4 seconds

4th retry

8 seconds

5th retry

16 seconds

6th retry

32 seconds

7th retry

64 seconds

8th retry

128 seconds

9th retry

256 seconds

10th retry

300 seconds (5 min max)

The retry schedule follows exponential backoff (2x multiplier) with a maximum delay of 5 minutes.

What Counts as Success?

  • Success: HTTP status codes 200-299

  • Failure: All other status codes, timeouts, or connection errors

Your Endpoint Should

  1. Respond quickly - Return a 200 status code immediately, then process asynchronously

  2. Handle duplicates - Use eventId for idempotency; you may receive the same event more than once

  3. Log failures - Track and investigate webhook processing failures

  4. Be available - Ensure your endpoint is highly available to receive webhooks

Example: Idempotent Processing


Monitoring Webhook Activity

Query your webhook logs to monitor delivery status and troubleshoot issues:

Log Status Values

Status
Description

PENDING

Delivery in progress

DELIVERED

Successfully delivered (2xx response)

RETRYING

Failed, waiting for retry

FAILED

All retry attempts exhausted

Example: Monitoring Script


Common Use Cases

ERP Integration

Sync component and BOM changes to your ERP system in real-time:

Slack Notifications

Alert your team about important component changes:

Audit Logging

Maintain a detailed audit trail of all changes:


Troubleshooting

Common Issues

Webhook not receiving events

  1. Check if webhook is enabled - Query the webhook and verify isEnabled: true

  2. Verify event subscriptions - Ensure the correct events are in the events array

  3. Check your endpoint - Verify your URL is accessible from the internet

  4. Review logs - Use the getLogs query to see delivery attempts and errors

Signature verification failing

  1. Check the secret - Ensure you're using the exact same signingSecret you configured

  2. Use raw body - Signature is computed on the raw JSON string, not a parsed object

  3. Check encoding - Ensure UTF-8 encoding throughout

Missing webhook deliveries

  1. Check retry status - Some deliveries may be queued for retry

  2. Verify library scope - Webhooks only fire for events in their configured library

  3. Check component filters - Events fire for all components in the library

Testing Your Webhook Endpoint

Before configuring a production webhook, test your endpoint:


Next Steps

Last updated

Was this helpful?