How to Build an On-Demand KPI Snapshot Returned to a Webhook Caller

Build a Spojit workflow that lets an external dashboard request live KPIs on demand: a Webhook trigger receives the request, a MySQL execute-query pulls the raw figures, the json and math connectors shape and round them, and a Response node returns the numbers synchronously in the same HTTP call.

What This Integration Does

Reporting dashboards often need a number that is current to the second: today's revenue, open orders, average basket size. Scheduling a nightly export is too stale, and giving a dashboard direct database access is risky. This workflow turns Spojit into a tidy read-only KPI endpoint. An external dashboard sends one HTTP POST naming the metric it wants, Spojit runs a single parameterized MySQL query against your reporting database, reshapes the result into a clean JSON payload, and hands the figures straight back to the caller. No data is stored in Spojit and nothing is written to your database, so the same endpoint can be called as often as a dashboard needs to refresh.

The run model is fully synchronous. The Webhook trigger receives the parsed JSON body, the workflow runs its steps in order, and a Response node returns the final object to the original caller within the same request. Because every call is independent and read-only, re-runs are naturally idempotent: calling the endpoint twice simply returns two fresh snapshots. If the database is briefly unavailable the run fails and the caller receives an error, so the dashboard can retry on its own schedule. You decide which metrics are allowed by mapping each requested metric name to a fixed SQL statement inside the workflow, never by passing raw SQL from outside.

Prerequisites

  • A MySQL connection in Spojit pointing at your reporting database or a read replica. Use a database user with read-only privileges so this endpoint can never modify data. See the MySQL connector article to set it up.
  • A Webhook signing connection so incoming requests are verified by HMAC. The schemes available are Spojit, Shopify, GitHub, Slack, and Custom. See Setting Up a Webhook Connection.
  • Knowledge of the table and column names that back each KPI you want to expose (for example an orders table with total, status, and created_at columns).
  • The external dashboard (or whatever calls the endpoint) must be able to send an HTTP POST with a JSON body and the required signature header.

Step 1: Add a Webhook trigger and capture the request

Open the Workflow Designer, create a new workflow, and set the Trigger type to Webhook. Attach your Webhook signing connection so requests are HMAC-verified. Copy the generated workflow URL: this is what the dashboard will call. The trigger output is the parsed JSON body, available downstream as {{ input }}. Design the caller to send a small request that names the metric and any bounds, for example:

{
  "metric": "todays_revenue",
  "from": "2026-06-21",
  "to": "2026-06-21"
}

The Webhook trigger returns 202 with an executionId on receipt, and the Response node you add later delivers the synchronous body. See Setting Up a Webhook Trigger for the full request contract.

Step 2: Validate the requested metric with a Condition node

Add a Condition node so the workflow only ever runs queries you have approved. Branch on {{ input.metric }} and check that it equals one of your known metric names, such as todays_revenue, open_orders, or avg_order_value. Route the matching case to the next step and route the false branch to a Response node (added in Step 6) that returns a clear error like { "error": "Unknown metric" }. This keeps the endpoint a fixed menu of safe KPIs rather than an open query surface. For branching mechanics see Using Condition Nodes.

Step 3: Run the KPI query with a MySQL Connector node

Add a Connector node in Direct mode on the mysql connector and choose the execute-query tool. Direct mode is deterministic and costs no AI credits, which is what you want for a predictable read. Map the query field to a fixed SQL statement for the matched metric, and pass the request bounds through the params array so the values are parameterized rather than concatenated into the SQL. For todays_revenue the statement looks like this:

SELECT
  COUNT(*)        AS order_count,
  SUM(total)      AS gross_revenue,
  AVG(total)      AS avg_order_value
FROM orders
WHERE status = 'paid'
  AND created_at >= ?
  AND created_at < DATE_ADD(?, INTERVAL 1 DAY)

Set params to ["{{ input.from }}", "{{ input.to }}"] so each ? placeholder is bound safely. Binding values through params instead of inlining them keeps the query both safe and cacheable. The tool returns the matching rows, available downstream as the node's output (for example {{ mysql_result.rows }} if you name the output variable mysql_result).

Step 4: Shape the raw result with the json connector

Database drivers often return numeric aggregates as strings and wrap everything in a rows array. Add a Connector node in Direct mode on the json connector to pull out just the single summary row and the fields you care about. Use the get tool to read the first row, for example a path of rows.0 against the MySQL output, then use the pick tool to keep only order_count, gross_revenue, and avg_order_value. If you prefer one step, the query tool can select a value by path. The result is a flat object such as:

{
  "order_count": 142,
  "gross_revenue": "18342.5",
  "avg_order_value": "129.17"
}

For the full list of path and reshaping tools see JSON Tools.

Step 5: Round and format the figures with the math connector

Add a Connector node in Direct mode on the math connector to turn raw aggregates into presentation-ready numbers the dashboard can show without further work. Use the round tool to fix avg_order_value to two decimal places, and use the currency tool to render gross_revenue as a formatted amount (for example $18,342.50) for any field the dashboard displays directly. The format tool adds thousands separators to integer counts. If the same node needs several derived numbers (a rounded value plus a formatted string), chain a short sequence of math Connector nodes, each writing its own output variable. Combine the rounded numeric values and the formatted display strings into one object with a Transform node so the response carries both a machine-readable figure and a human-readable label. See Math Tools for every available operation.

Step 6: Assemble the payload and return it with a Response node

Add a Transform node to build the exact object you want the dashboard to receive, pulling from the json and math outputs. Then add a Response node, which returns a value to the synchronous webhook caller, and map its body to the Transform output. A clean snapshot payload looks like this:

{
  "metric": "{{ input.metric }}",
  "asOf": "{{ now }}",
  "orderCount": 142,
  "grossRevenue": 18342.50,
  "grossRevenueDisplay": "$18,342.50",
  "avgOrderValue": 129.17
}

Wire the success branch of your Condition node through Steps 3 to 6 into this Response node, and wire the unknown-metric branch into a second Response node returning the error object. The caller receives whichever Response node the run reaches. For the Response node contract see Using Response Nodes. If you want Spojit to scaffold the canvas, describe it to Miraxa, the intelligent layer across your automation, with a prompt like "Add a MySQL Connector node in Direct mode using execute-query, then a json pick node, then a math round node, then a Response node."

Tips

  • Keep each metric's SQL as a fixed statement chosen by the Condition branch. Never build SQL from request text, and always pass dynamic values through params.
  • Point the MySQL connection at a read replica if you have one, so heavy dashboard polling never competes with your production write traffic.
  • Use the now variable or the date connector to stamp asOf in the response so the dashboard can show how fresh each snapshot is.
  • If a single dashboard refresh needs several KPIs, accept a list of metric names and use a Loop node, or run independent queries in a Parallel node and merge the results before the Response.

Common Pitfalls

  • Returning before the data is ready: the Response node returns whatever has run so far, so make sure the MySQL, json, and math steps all sit upstream of it on the same branch.
  • Timezone drift on date bounds: a "today" filter depends on the database server timezone. Pass explicit from and to dates from the caller, or normalize them with the date connector, rather than relying on CURDATE() alone.
  • String versus number types: SUM and AVG can come back as strings. Run them through the math connector before returning, or the dashboard may try to add strings.
  • Missing or invalid signature: an unsigned or wrongly signed request is rejected by the Webhook trigger before the workflow runs. Confirm the dashboard sends the correct HMAC header for your signing scheme.

Testing

Before pointing your live dashboard at the endpoint, test with a single known metric and a narrow date range you can verify by hand. Send one POST to the workflow URL with { "metric": "todays_revenue", "from": "2026-06-21", "to": "2026-06-21" } and confirm the returned figures match a manual query. Then send a deliberately bad metric name to confirm the Condition branch returns the error object instead of running a query. Watch each run in the execution history to see the MySQL, json, and math outputs at every step; see Monitoring Workflow Executions. Once a handful of calls return correct, well-typed numbers, enable the workflow and let the dashboard poll it.

Learn More

Did this answer your question? Thanks for the feedback There was a problem submitting your feedback. Please try again later.