Skip to content
Webhook

Docs contents

Business and custom data

Receive updates with an inbound webhook

Let a script or automation send selected JSON values to Denframe, instead of Denframe polling for them.

You’ll have

A Custom block showing the revenue and attainment your producer last sent, 124500 EUR and 83%, that shows as delayed when deliveries stop.

You’ll need
  • Denframe installed and running: macOS, Windows or Home Assistant.
  • A receiving route, set up by an administrator, that the producer can reach.
  • For a remote producer, an approved HTTPS origin pointing at the management service’s ingestion route. Denframe doesn’t create the proxy, DNS or certificate.
  • A producer that can POST JSON with an Authorization header.

Follow these steps in your own Denframe. This website never connects to your household, your accounts or your devices, and never asks for your credentials.

  1. Prepare the receiving address

    Set DENFRAME_INGEST_BASE_URL to your HTTPS origin, for example https://ingest.example.com, before starting Denframe. Expose only the ingestion POST route through your approved proxy, and configure trusted proxy peers and forwarded HTTPS and host headers as your host deployment requires.

    Host environment example
    export DENFRAME_INGEST_BASE_URL="https://ingest.example.com"

    Don’t expose the administration interface just to receive an event. A desktop receiver-only listener cannot accept ingestion, and cloud producers cannot reach localhost or a private LAN address without an approved delivery route.

  2. Open the webhook connection

    In Studio, open Sources, then Custom. Choose Add a custom source; the sheet asks where the data comes from.

    Choose Inbound webhook. For this example, keep Producer on Generic / Home Assistant and set Name to Sales feed.

  3. Map a sample

    Paste the JSON below into Sample JSON from the data field. Paste only these values, not the outer delivery envelope.

    Paste this setup sample
    {
      "revenue": 124500,
      "attainment_pct": 83,
      "currency": "EUR"
    }

    Choose Choose fields from sample. Map the first value to the Metric /revenue and add a second value with the Range /attainment_pct, Minimum 0 and Maximum 100.

    Set Expected delivery interval (seconds) to how often your producer will send.

    A pasted sample stays in a private setup session for ten minutes and is never published to a dashboard.

  4. Add the source and copy the token

    Choose Preview selected values, pick the value in Value to show, tick the dashboard under Show on, then choose Add source.

    The Send data to this webhook sheet shows the Delivery address and the Delivery token (shown once). Copy both into the producer’s protected configuration (Copy token copies the token) before you close the sheet; the address is complete, including any configured URL prefix. Then choose Done to attach the value.

    The source stays Waiting for data until a real event arrives. Saving a pasted sample doesn’t count as a delivery.

  5. Send one real event

    Run this Python example on the producer, with DENFRAME_WEBHOOK_URL set to the copied address and DENFRAME_WEBHOOK_TOKEN supplied from its protected configuration. It creates the timestamp at send time and a unique event ID. Replace the synthetic data with values from your system. No extra Python package is needed.

    Python 3 producer example
    import datetime
    import json
    import os
    import uuid
    import urllib.request
    
    event = {
        "schema_version": 1,
        "event_id": str(uuid.uuid4()),
        "produced_at": datetime.datetime.now(datetime.timezone.utc).isoformat(),
        "data": {"revenue": 124500, "attainment_pct": 83, "currency": "EUR"},
    }
    request = urllib.request.Request(
        os.environ["DENFRAME_WEBHOOK_URL"],
        data=json.dumps(event).encode("utf-8"),
        headers={
            "Content-Type": "application/json",
            "Authorization": "Bearer " + os.environ["DENFRAME_WEBHOOK_TOKEN"],
        },
        method="POST",
    )
    with urllib.request.urlopen(request, timeout=10) as response:
        print(response.status, response.read().decode("utf-8"))
  6. Schedule it and retry safely

    Schedule the producer at your intended interval and keep Expected delivery interval (seconds) matching it. Stop sending for a while to confirm the value becomes delayed rather than Denframe inventing new values.

    For a delivery retry, reuse the exact event ID, timestamp and data of the original event. Make a new envelope only for a new observation; a retry must never become a newer reading.

    To replace the token, open the source and choose Replace delivery token, update the producer’s protected configuration, and send a new event with a newer timestamp. The old token stops working immediately, and the source’s values are cleared until that newer event arrives.

  7. Check it worked

    Check the producer gets an HTTP 200 response. Then open the source: Recent deliveries lists the accepted event (choose Reload delivery history to refresh it), and the selected dashboard shows 124500 EUR and 83%.

    Check delivery on the Send data to this webhook sheet shows the last accepted delivery while setup is still open.

If it doesn’t work

No receiving address is shown

Configure the ingest base URL and delivery route, then open the source and choose View sending instructions again. A producer running on the Denframe host itself can instead POST over loopback to the Delivery path.

Unauthorized

Use the source’s own delivery token, not a Denframe admin or display credential. If you lost the one-time token, choose Replace delivery token and update the producer.

409 or an ignored event

A 409 means the source is paused or changed, or the event ID was already used with different content. An event is ignored when its production time is not newer than the latest accepted reading.

422 for the timestamp

The production time must carry a time-zone offset, be within the last seven days and be no more than five minutes ahead. Check the host and producer clocks.

429 Too Many Requests

Each source accepts up to 60 deliveries a minute, and each sender up to 120 attempts. Wait for the Retry-After time before sending again.

Browser request fails

Send from a server-side producer. Ingestion rejects browser-origin and compressed requests.

Related guides