---
title: "Run App Query Batch"
method: POST
path: "/api/v1/apps/{app_id}/query/batch"
tags: ["apps-query"]
---

# Run App Query Batch

`POST /api/v1/apps/{app_id}/query/batch`

Run several guarded SELECTs against the app's bound entities in one
request with bounded, cancellation-aware DuckDB execution.

App-level failures (missing / not ready) return 404 / 409. Per-query
failures (bad SQL, DuckDB errors) are isolated into each result's
``error`` field with HTTP 200 — one broken widget never blanks the page.

## Path parameters

- `app_id` string, uuid, required

## Request body

- AppQueryBatchRequest — Body for POST /api/v1/apps/{app_id}/query/batch. Coordinates every query in one bounded execution lifecycle instead of N independent requests. Each query is routed to a read lane independently (see ``domains.apps.adapters.routed_query_engine``), so one batch can span both: the OLTP sub-batch goes through ``EntityOltpRead.run_sql_batch`` bounded by ``ENTITY_STORE_QUERY_CONCURRENCY``, the OLAP sub-batch through ``EntityOlapRead.run_sql_batch``. Per-query errors are isolated — a failing query returns its ``error`` field without aborting the rest — and so is each item's ``lane`` / ``mirror_refreshed_at``.
  - `queries` AppQueryBatchItem[], required
    - `id` string, required
    - `sql` string, required
    - `limit` integer, nullable
  - `embed_host_app_id` string, uuid, nullable — Set when this app is running as an embedded widget inside another app. Authorization then requires VIEWER on that host plus an active embed binding — see domains/apps/application/embed_access.py.

## Response `200`

Successful Response

- AppQueryBatchResponse
  - `results` AppQueryBatchItemResult[], required
    - `lane` 'oltp' | 'olap'
    - `mirror_refreshed_at` string, date-time, nullable
    - `id` string, required
    - `columns` string[], required
    - `rows` object[], required
    - `total_rows` integer, required
    - `truncated` boolean, required
    - `error` string, nullable

## Other responses

- `422` — Validation Error

## Changes

- **2026-08-28** `ef8b72834a51` — 2 info
  - added the optional property `results/items/lane` to the response with the `200` status
  - added the optional property `results/items/mirror_refreshed_at` to the response with the `200` status
- **2026-08-21** `8de9cb14f744` — 1 info
  - added the new optional request property `embed_host_app_id`

[Change history](https://skmtc.dev/netter/apis/dmi-backend/changes/api/v1/apps/:app_id/query/batch/post.md)

---

[API](https://skmtc.dev/netter/apis/dmi-backend.md) · [All operations](https://skmtc.dev/netter/apis/dmi-backend/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/netter/dmi-backend/revisions/eed6fb164abd/schema)
