← Back to Docs
Last updated: 2026-09-22

Webhooks

Webhooks let InvyMate push events to your system automatically, instead of your integration polling APIs.

Plan availability

  • Webhooks are available on plans that include the webhook feature.

Where to configure

  • Go to Configuration → Webhooks
  • Create one or more endpoints

Quick start

  1. Create an endpoint and choose the event types you want.
  2. Save the signing secret when it is shown.
  3. Verify the destination endpoint.
  4. Trigger a real event.
  5. Review delivery history and replay failures if needed.

Webhook events are forward-only: InvyMate sends an event only to endpoints that are active, verified, and subscribed when that event occurs. Enabling, verifying, or changing an endpoint does not send past events.

Verify webhook signatures

InvyMate signs every delivery so your receiver can confirm that it came from InvyMate and was not changed in transit. Keep the secret on your server and never expose it in browser code, URLs, or logs.

For a runnable Node.js receiver, see the InvyMate webhook receiver example on GitHub.

Every delivery includes this header:

X-InvyMate-Signature: t=1727000000,v1=9f5c...
  • t is the Unix timestamp used for the signature.
  • v1 is the HMAC-SHA256 signature.

The signed value is the timestamp, a period, and the exact raw request body:

signed_value = timestamp + "." + raw_request_body
expected_signature = HMAC-SHA256(webhook_secret, signed_value)

Verify the signature before parsing or re-serializing the JSON body. Compare signatures using a constant-time comparison and reject timestamps outside a short tolerance window, such as five minutes.

Example in Python:

import hashlib
import hmac
import time

def verify_invymate_signature(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(part.split("=", 1) for part in header.split(",") if "=" in part)
    timestamp = parts.get("t")
    received_signature = parts.get("v1")
    if not timestamp or not received_signature:
        return False

    if abs(time.time() - int(timestamp)) > 300:
        return False

    signed_value = timestamp.encode("ascii") + b"." + raw_body
    expected_signature = hmac.new(
        secret.encode("utf-8"),
        signed_value,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected_signature, received_signature)

Return 401 for a missing or invalid signature. Return a 2xx response only after the signature has been accepted.

Verification handshake

When you click Verify, InvyMate sends a signed event with type webhook.endpoint.verification. The challenge is in data.challenge:

{
  "version": "v1",
  "type": "webhook.endpoint.verification",
  "eventId": "...",
  "createdAt": "2026-09-22T15:20:22.796Z",
  "data": {
    "endpointId": "...",
    "challenge": "..."
  }
}

After validating the signature, return the same challenge in a 2xx JSON response:

{
  "challenge": "..."
}

The endpoint becomes verified only when InvyMate receives a successful response with the matching challenge.

Delivery headers and idempotency

In addition to the signature, deliveries include:

  • X-InvyMate-Event — event type.
  • X-InvyMate-Event-Id — event identifier.
  • X-InvyMate-Delivery-Id — stable identifier for this delivery.
  • X-InvyMate-Delivery-Attempt — attempt number.
  • X-InvyMate-Delivery-Attempt-Id — identifier for this attempt.

Use X-InvyMate-Delivery-Id to make processing idempotent. A receiver must be prepared to receive the same delivery more than once. Store the delivery ID before performing a non-repeatable action, and return 2xx for an already-processed delivery.

Delivery history and replay

Webhook delivery history is kept for 7 days. You can replay an event or delivery during that window; after it expires, it is permanently removed.

Typical endpoint fields

  • Name
  • Destination URL
  • Subscribed event types
  • Active or inactive state
  • Verification status

Current event types

  • asset.created
  • asset.status.changed
  • asset.location.changed
  • asset.assigned
  • asset.unassigned
  • person.created
  • person.updated

Good webhook setup practices

  • keep the signing secret in your server-side environment only
  • use HTTPS for the destination URL
  • reject old signatures to reduce replay risk
  • return 2xx quickly and process business work asynchronously
  • log delivery IDs and response status, but never log the signing secret
  • make receivers idempotent in case the same event is delivered again
  • use delivery history in InvyMate when testing changes

We value your privacy

We use cookies to enhance your browsing experience, serve personalized ads or content, and analyze our traffic. By clicking "Accept All", you consent to our use of cookies. Read our Cookie Policy to learn more.