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
- Create an endpoint and choose the event types you want.
- Save the signing secret when it is shown.
- Verify the destination endpoint.
- Trigger a real event.
- 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...
tis the Unix timestamp used for the signature.v1is 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.createdasset.status.changedasset.location.changedasset.assignedasset.unassignedperson.createdperson.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
2xxquickly 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