How to Run On-Demand SQL Queries via Webhook with a Response

Build a Spojit workflow that accepts a webhook request with query parameters, runs a parameterized MySQL query, and returns the matching rows synchronously to the caller through a Response node.

What This Integration Does

Sometimes another system needs to read live data out of your MySQL database without being granted direct database access. This workflow turns a single MySQL query into a safe, on-demand HTTP endpoint: a caller sends a webhook request with a couple of parameters (for example a customer ID and a status), Spojit runs a parameterized SELECT, and the rows come back in the same HTTP response. You decide exactly which query runs, so the caller never writes SQL and never touches the database directly.

The run model is synchronous. The Webhook trigger receives an HTTP POST, the workflow runs the MySQL Connector node in Direct mode, a JSON Connector node shapes the result, and a Response node returns the payload to the original caller in the same request. Because every call uses placeholder parameters bound at run time, the query shape is fixed and re-runs are read-only and side-effect free: the same input always returns the current rows for that input, and nothing is written back to the database.

Prerequisites

  • A MySQL connection configured under Connections, pointing at the database you want to read from. A read-only database user is strongly recommended for this workflow.
  • A signing connection for the webhook (scheme Spojit, Custom, or another supported scheme) so the trigger can verify incoming requests. See the related article on adding connections below.
  • Knowledge of the table and columns you want to expose, and which input values the caller will send (for example customerId and status).
  • The caller must be able to send an HTTP POST and read the synchronous response body.

Step 1: Add a Webhook trigger

Start a new workflow and set the trigger. Open the Trigger node, choose Webhook as the trigger type, and select your signing connection so incoming requests are verified by HMAC. Save to reveal the workflow's webhook URL and copy it for the caller.

The trigger output is the parsed JSON body, available downstream as {{ input }}. Design your caller to POST a small JSON object, for example:

{
  "customerId": 4821,
  "status": "open"
}

Reference these later as {{ input.customerId }} and {{ input.status }}.

Step 2: Run the query with the MySQL connector in Direct mode

Add a Connector node, choose the MySQL connector, and set it to Direct mode so exactly one tool runs with no AI cost. Select the execute-query tool. This tool takes two fields: a query string and an optional params array of values that fill the ? placeholders in order.

Always use placeholders for caller-supplied values: never paste {{ input.* }} directly into the SQL string. Set query to a fixed statement and map each placeholder through params:

SELECT id, customer_id, status, total, created_at
FROM orders
WHERE customer_id = ?
  AND status = ?
ORDER BY created_at DESC
LIMIT 100

Set params to the ordered list of values:

[ {{ input.customerId }}, {{ input.status }} ]

The placeholders bind the caller's input safely, keeping the query shape fixed regardless of what the caller sends. Bind the result to an output variable such as queryResult.

Step 3: Validate the input before querying (optional but recommended)

To reject malformed calls early, add a Condition node before the MySQL node. For example, branch on whether {{ input.customerId }} is present and numeric. Wire the false branch to a Response node that returns an error payload (see Step 5) so the caller gets a clear message instead of an empty result. Keep the true branch flowing into the MySQL Connector node from Step 2.

Step 4: Shape the result with the JSON connector

The rows returned by execute-query may carry more structure than the caller needs. Add a Connector node, choose the JSON connector in Direct mode, and use a tool such as pick to keep only the fields you want to expose, or get to drill into the rows array. For instance, use pick to retain id, status, and total per row, then bind the cleaned output to a variable such as rows. This keeps your public response stable even if the underlying table gains columns later. If the raw rows are already exactly what you want to return, you can skip this step.

Step 5: Return the rows with a Response node

Add a Response node as the final step on the success path. The Response node returns a value to the synchronous webhook caller, closing the same HTTP request the trigger opened. Set the response body to the shaped data, including a small wrapper so the caller can read a count and the rows together:

{
  "ok": true,
  "count": {{ rows.length }},
  "rows": {{ rows }}
}

On the validation-failure branch from Step 3, point its own Response node at an error body such as { "ok": false, "error": "customerId is required" }. Each path ends in exactly one Response so the caller always receives a definitive answer.

Step 6: Save, enable, and share the endpoint

Save the workflow and enable it. Copy the webhook URL from the trigger and give it, together with the signing details, to the system that will call it. From here, every POST runs the fixed query with the caller's parameters and returns the current rows in the response body. If you ever need to change the columns or filters, edit the query and params in the MySQL node; the endpoint URL stays the same.

Tips

  • Always add a LIMIT to the SELECT so a broad call cannot return an unbounded result set into the response.
  • Use a read-only MySQL connection for this workflow so an unexpected query shape can never modify data.
  • If a caller needs to pass many filters, accept them as named fields in the JSON body and map each one to its own ? placeholder in params, keeping the order identical to the placeholders.
  • You can ask Miraxa, the intelligent layer across your automation, to scaffold this on the canvas: try "Add a Webhook trigger, a MySQL Connector node in Direct mode running execute-query, and a Response node, and connect them in order," then fine-tune the query in the properties panel.

Common Pitfalls

  • Interpolating {{ input.* }} directly into the SQL string instead of using params. Keep the query fixed and bind values through placeholders so untrusted input cannot alter the statement.
  • Forgetting the Response node. Without it the caller's HTTP request never receives the rows, even though the query ran successfully.
  • Mismatched placeholder order: the values in params must line up with the ? positions in query, left to right.
  • Returning raw database column names that later get renamed. Shape the output with the JSON connector so your public response stays stable as the schema changes.

Testing

Before sharing the endpoint, test on a narrow scope. Use a known customerId that you can verify by hand, POST a sample body to the webhook URL, and confirm the response count and rows match what you expect from the database. Check the validation branch by sending a body that omits customerId and confirming you get the error response, not an empty success. Review the run in your execution history to see the exact query, the bound parameters, and the returned rows for each step before turning the endpoint over to the calling system.

Learn More

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