---
title: "Repo Query"
method: POST
path: "/v1/teams/{team_id}/repo/query"
tags: ["team repo"]
---

# Repo Query

`POST /v1/teams/{team_id}/repo/query`

## Request

- Base URL: `https://api.stormy.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.stormy.ai/v1/teams/{team_id}/repo/query`
- Auth: none declared

Answer a SQL question about this tree. SELECT only, always read-only.

THE FRONTMATTER IS THE SCHEMA. Every `key: value` in the tree becomes a row
in `fields`, so a field this shop invented this afternoon is queryable this
afternoon and nothing has to be added here for it to work. The columns on
`docs` are only the concepts the whole product already shares a definition
of — settled, waiting, due — promoted so that this route and the open-loops
block cannot come to disagree about the same file.

THE WORKING TREE, NOT THE BARE REPO. `_repo_for` falls back to a bare
repository, which is right for browsing a ref and wrong here: this reads
files off disk, and a bare repo has none. It is a 409 rather than a silent
empty result, because "no rows" and "nowhere to look" are different answers
and a model cannot tell them apart.

THE BODY IS `{"sql": "SELECT …", "limit": 60}` — and `query`, `q`, `select`
and `statement` land on the same field, because no code in this repository
writes this body and a model that guessed one of those was refused for a
word rather than for a mistake. See `TreeQuery`.

## Path parameters

- `team_id` string, uuid, required

## Headers

- `authorization` string, nullable
- `x-darwin-token` string, nullable

## Request body

- TreeQuery: One model-written SELECT over this team's tree. EVERY SPELLING OF "THE SQL" IS THE SAME FIELD (owner, 2026-09-12, after a run of `422 … reasons=sql: Field required` in the api log). Nothing in this repository builds this body: the caller is a model that read one table row in `harnesses/AGENT.md` saying the route takes SQL, and then wrote the key it would have written anywhere else -- `query`, `q`, `select`, `statement`. A refusal taught it nothing, because a 422 that names OUR word cannot be read by a caller that does not know our word. This is the same fix as `/repo/record` taking `?ref=` beside `?path=`: one meaning, every spelling a competent caller would reach for. `limit` ACCEPTS `None`. A model that fills a field it does not care about writes `null` there, and a `null` should never cost the whole question -- the route clamps it anyway.
  - `sql` string
  - `limit` integer, nullable

## Response `200`

Successful Response

- object

## Other responses

- `422`: Validation Error

## Changes

> 70 revisions in range; 1 not diffed.

- **2026-09-13** `33afbf889154`: 3 info
  - the request property `sql` became optional
  - the `sql` request property default value `` was added
  - request property `limit` list-of-types was widened by adding types `null` to media type `application/json`

[Operation history](https://skmtc.dev/stormy/apis/stormy-control-plane/changes/v1/teams/:team_id/repo/query/post.md)

---

[API](https://skmtc.dev/stormy/apis/stormy-control-plane.md) · [All operations](https://skmtc.dev/stormy/apis/stormy-control-plane/llms.txt) · [OpenAPI document](https://skmtc.dev/stormy/apis/stormy-control-plane/revisions/4d811ab18158?raw)
