Execute → JSON
Operation RESTFetch a template's full record tree as a compact nested JSON array. The default format for all programmatic consumers.
Endpoints
Two equivalent endpoints return the same JSON payload. Use the explicit .json suffix when your client sets Accept headers dynamically and you need format pinning regardless of header negotiation:
| Method | URL | Format |
|---|---|---|
| GET | /api/v1/expressions/multiquery/{templateCode} |
JSON (default) |
| GET | /api/v1/expressions/multiquery/{templateCode}.json |
JSON (explicit) |
Request
Headers
| Header | Value | Required |
|---|---|---|
Authorization |
Bearer {token} |
Yes |
Accept |
application/json |
Recommended |
Path Parameters
| Parameter | Type | Description |
|---|---|---|
templateCode |
string |
The catalogue code identifying the Multi-Query template stored in
dbo.Shared_Configurations. Must match the Code column exactly
(case-insensitive).
|
Query Parameters
Any additional query string parameters are forwarded to the template engine as named SQL
parameters. The engine matches them to @ParamName placeholders in any SQL
node within the template tree. Parameter names are case-insensitive.
GET /api/v1/expressions/multiquery/PAYROLL_SUMMARY?DepartmentID=42&PayPeriod=2026-05
Authorization: Bearer eyJ...
In the example above, @DepartmentID and @PayPeriod become
available in every SQL node of the template. @TenantID is always injected
from the JWT and must not be passed by the caller.
Response Shape
The response is a JSON array at the root level. Each element represents one row from the
root query. Nested child collections appear as named array properties on each row object.
The property name for each child collection is taken from the collectionName
field in the template definition.
// Structural schema
[
{
// ... columns from root query row
"childCollectionName": [
{
// ... columns from child query row
"grandchildCollectionName": [
{
// ... columns from grandchild query row
}
]
}
]
}
]
TenantID is extracted from the caller's JWT and injected into every SQL node in the template tree — at every depth. The caller cannot pass or override TenantID via query string or request body. This guarantees strict tenant isolation across all nested queries.
Sample Response
The following example shows a three-level hierarchy: Employees → Payslips → Deductions. Each level is represented as an inline nested array on its parent object.
[
{
"EmployeeID": 1,
"FirstName": "Alice",
"LastName": "Nguyen",
"DepartmentID": 42,
"DepartmentName": "Engineering",
"payslips": [
{
"PayslipID": 101,
"Period": "2026-05",
"GrossPay": 5000.00,
"NetPay": 3850.00,
"ProcessedOn": "2026-05-25T00:00:00",
"deductions": [
{
"DeductionID": 201,
"Type": "Tax",
"Amount": 1000.00,
"RuleRef": "TAX-PAYE-2026"
},
{
"DeductionID": 202,
"Type": "NationalInsurance",
"Amount": 150.00,
"RuleRef": "NI-CLASS1-2026"
}
]
},
{
"PayslipID": 102,
"Period": "2026-04",
"GrossPay": 5000.00,
"NetPay": 3850.00,
"ProcessedOn": "2026-04-25T00:00:00",
"deductions": [
{
"DeductionID": 198,
"Type": "Tax",
"Amount": 1000.00,
"RuleRef": "TAX-PAYE-2026"
}
]
}
]
},
{
"EmployeeID": 2,
"FirstName": "Marcus",
"LastName": "Bell",
"DepartmentID": 42,
"DepartmentName": "Engineering",
"payslips": []
}
]
Key observations from the sample above:
- Employee 2 (Marcus Bell) has an empty
payslipsarray — this is normal when no child rows exist. - Collection names (
payslips,deductions) are defined in the template, not inferred from table names. - Date/time values are returned as ISO 8601 strings.
- Numeric values retain their SQL precision (decimal, not rounded).
Error Responses
| HTTP Status | Meaning | Common Cause |
|---|---|---|
401 Unauthorized |
Missing or invalid JWT | Token expired, missing Authorization header, or invalid signature |
403 Forbidden |
Insufficient role | Caller's JWT does not include the TenantAdmin role required for this endpoint |
404 Not Found |
Template not found | templateCode does not match any record in dbo.Shared_Configurations for the caller's tenant |
429 Too Many Requests |
Rate limit exceeded | ApiLimit("MultiQuery.Execute") threshold reached — retry after the interval indicated in the Retry-After response header |
500 Internal Server Error |
Execution failure | SQL error in one of the template nodes, missing required parameter, or database connectivity issue |
Rate Limiting
This endpoint is protected by the ApiLimit("MultiQuery.Execute") rate limit
policy. Limits are configured per tenant by a platform administrator and are not exposed
in this documentation. When a limit is exceeded, the server responds with
429 Too Many Requests and a Retry-After header indicating
when the limit window resets.
For high-frequency consumers, consider using the cacheSeconds property in
your template definition to serve repeated identical requests from cache without incurring
additional database queries or rate-limit credits.