❮  Integrations

Webhook specification

Entrixy sends an Open command to your address and signs it. Here is the request format and how to verify the signature, so you can accept the command in your own service, smart home or board.

A webhook is the mode where the opening is performed not by our controller but by your own system: Home Assistant, a relay on the local network, your own server. A Webhook object has two modes: app — the phone itself makes the HTTP request to your address, filling values into the URL template; server — our server sends a signed POST, which is what this page describes. Ready-made receivers: curl, Flask, Home Assistant, Node.js.

The request

On opening, the Entrixy server sends a POST to your webhook_url with a JSON body:

POST <your webhook_url>
Content-Type: application/json

{
  "action":    "open",
  "object_id": 42,
  "timestamp": 1750000000,
  "nonce":     "0011223344556677",
  "signature": "9d7b58066094fa88..."
}
FieldValue
action"open" (for bistable objects also "close")
object_idthe object id in your account
timestampunix send time, in seconds
nonce16 hex characters (8 random bytes), single use
signatureHMAC-SHA256, see below

The fields timestamp, nonce and signature arrive only if the object has a webhook_secret. Without a secret the body carries only {action, object_id}.

The signature

What is signed is a canonical string of four dot-separated fields, not the JSON body itself, so you do not have to reproduce our serialisation byte for byte:

base = "<timestamp>.<nonce>.<action>.<object_id>"
signature = HMAC-SHA256(webhook_secret, base)   // hex

webhook_secret is set when you create the Webhook object in the app. Guests never receive it — the server signs with your secret itself.

How to verify it (on your side)

  1. Build the same string base = timestamp.nonce.action.object_id from the fields you received.
  2. Compute HMAC-SHA256(webhook_secret, base) and compare it with signature using a constant-time comparison (hash_equals / hmac.compare_digest).
  3. Anti-replay: reject the request if |now − timestamp| > 300 seconds. Optionally, keep recent nonce values and reject repeats.
  4. The signature matches and the request is fresh — perform the opening.
A webhook address is usually open without authentication, so verifying the signature is mandatory. Use a secret of at least 16 characters, or better still generate one: openssl rand -hex 32.

Test vector

Run your verification against these values and check the signature:

webhook_secret = webhook_secret_example_key
timestamp      = 1750000000
nonce          = 0011223344556677
action         = open
object_id      = 42

base       = 1750000000.0011223344556677.open.42
signature  = 9d7b58066094fa88acc0afa7aa805fc5f0d008d33cb11b8aa2366102da8e20f1
  = HMAC-SHA256(webhook_secret, base)

The response (optional)

Answer with 200 OK. To have the app show a result, return the JSON {"level":"success","message":"..."} (level: success/warning/danger/info). Otherwise just 200.

Ready-made receivers

curl (test send and verify), Flask and Node.js (service skeletons), Home Assistant (a webhook automation with HMAC). Relays without HMAC support (Shelly, Tasmota) connect through a proxy or Home Assistant.