Skip to content

Query REST API

Read-only HTTP API over a READY scan of your workspace. Default: LATEST READY for the canonical workspace. Override with ?scanId= (pin one scan) or ?workspaceId= (LATEST for another workspace).

Base URL: https://helix-flow.igentify.in
Programmatic access: @igentify/helix-flowgraph (queryGraph, queryFeatures, …).
Prefer GET through CloudFront (POST on some routes may hit the SPA fallback).


What you are querying

Helix materializes each scan as a technical graph:

  • Nodes — code entities (routes, services, React components, HTTP client calls, product features, …)
  • Edges — relationships (CALLS, HANDLED_BY, CALLS_REMOTE, USES, …)
  • Features — product capabilities resolved from features/*.yaml plus synthetic FE↔BE bridge features

The API never runs your code. It answers questions like:

  • Which backend endpoint handles this UI call?
  • What code sits in the neighbourhood of a feature?
  • If I change node X, which features are affected?
  • What did the AI pass note about risks or behaviour on this endpoint?

Pipeline background: How Helix works. Vocabulary: Glossary.


Quick start

bash
export BASE=https://helix-flow.igentify.in
export TOKEN="<cognito-id-token>"
export AUTH="X-Helix-Authorization: Bearer $TOKEN"

# 1. Discover features (cheap — good first call)
curl -sS "$BASE/query/features" -H "$AUTH"

# 2. Pick a feature id from the list, e.g. feature:enrollments:…
curl -sS "$BASE/query/feature?featureId=feature:…" -H "$AUTH"

# 3. Or narrow to one repository
curl -sS "$BASE/query/repo-graph?repoKey=ng-access-service" -H "$AUTH"

TypeScript (@helix/shared):

typescript
import { helixQueryJson, loadTechnicalGraphFromQueryResponse } from "@helix/shared";

const config = {
  baseUrl: process.env.HELIX_QUERY_BASE_URL!,
  getIdToken: async () => process.env.HELIX_ID_TOKEN,
};

const { features, scanId } = await helixQueryJson<{ features: Feature[]; scanId: string }>(
  config,
  "/query/features",
);

const graph = await loadTechnicalGraphFromQueryResponse(
  await helixQueryJson(config, "/query/technical-graph"),
);

Every graph response includes scanId — treat it as the snapshot version. If you cache graph data, key by scanId.


Scan selection (0.2.1+)

All /query/* routes accept optional query parameters:

ParameterEffect
(none)LATEST READY for the canonical workspace (igentify / HELIX_WORKSPACE_ID)
scanIdLoad graph + AI artifacts from that READY scan in S3
workspaceIdLATEST READY for the given workspace (ephemeral pre-feature scans, etc.)
bash
# Default — canonical latest
curl -sS "$BASE/query/features" -H "X-Helix-Api-Key: $KEY"

# Historical / branch scan (after scan start + READY)
curl -sS "$BASE/query/repo-graph?repoKey=ng-access-service&scanId=01KX0JWPM83J" -H "X-Helix-Api-Key: $KEY"

# Latest in an alternate workspace
curl -sS "$BASE/query/features?workspaceId=pre-feature-enrollments" -H "X-Helix-Api-Key: $KEY"
typescript
await queryFeatures({ scanId: "01KX…" });
await queryRepos("ng-access-service", { workspaceId: "pre-feature-enrollments" });

Workflow for pre-feature branch comparison: POST /scan/start with repos[].commit → wait for READY → query with returned scanId. See NPM client — querying a previous scan.


Choosing an endpoint

Use the smallest response that answers your question.

GoalEndpointWhy
List product featuresGET /query/featuresSmall JSON; no graph load
Human labels for featuresGET /query/feature-display-titlesMap featureId → display string
One feature’s code neighbourhoodGET /query/feature?featureId=1-hop subgraph around the feature
Everything in one repoGET /query/repo-graph?repoKey=Filtered nodes/edges
Full workspace graphGET /query/technical-graphAll repos; largest payload
Compare two featuresPOST /query/compare-featuresShared vs unique implementation nodes
Blast radius of a code changePOST /query/impactFeatures with USES → your node
Walk the graph locallyPOST /query/nodeOne node + neighbour ids
Find where to implement somethingPOST /query/implementation-anchorHeuristic anchor lookup
AI notes on a backend routeGET /query/endpoint-qa?endpointId=Per-endpoint Q&A bundle
AI risks on a backend routeGET /query/endpoint-potential-issues?endpointId=Risk list
Same for frontend client callGET /query/endpoint-qa-fe?clientCallId=FE-side Q&A
AI feature summaryGET /query/feature-insights?featureId=Narrative + structured insights

Agent rule of thumb: start with /query/features or /query/repo-graph, drill into /query/feature or /query/node, call AI artifact endpoints only when you need prose or risk analysis—not as a substitute for graph structure.


Graph data model

Node id format

Technical nodes are repo-scoped:

text
repo:<repoKey>|<kind>:<path-or-symbol>

Examples:

  • repo:ng-access-service|ApiEndpoint:GET /users/{id}
  • repo:ng-work-space-ui|ApiClientCall:src/api/users.ts#getUser

Feature nodes use the feature: prefix (legacy scans may still contain flow:).

Common node labels

LabelMeaning
FeatureProduct capability (from YAML or FE↔BE bridge)
ApiEndpointBackend HTTP route / handler entry
ApiClientCallFrontend typed HTTP call site
ReactPage / ReactComponent / HookUI structure
Controller / Service / MethodBackend stack
Repository / Entity / DataModelPersistence layer

Full enum: shared/src/graph.tsGraphNodeLabel.

Common edge types

TypeMeaning
CALLSIntra-repo call
CALLS_REMOTEFE ApiClientCall → BE ApiEndpoint (cross-repo)
HANDLED_BYRoute stack → handler
USESFeature → implementation node
CALLS_APIUI → client call
IMPORTSModule dependency

Walk sequences by following outgoing edges from an ApiEndpoint or ApiClientCall. Cross-repo behaviour requires CALLS_REMOTE.

Node fields

json
{
  "id": "repo:ng-access-service|Method:src/users/users.service.ts#findById",
  "label": "Method",
  "name": "findById",
  "repository": "ng-access-service",
  "filePath": "src/users/users.service.ts",
  "summary": "optional AI one-liner",
  "data": { "httpMethod": "GET", "path": "/users/:id" }
}

Use filePath + repository to map graph nodes back to source files for edit suggestions.


Endpoint reference

GET /query/features

Returns: { features: FeatureSummary[], scanId }

json
{
  "features": [
    { "id": "feature:bridge:…", "name": "User enrollment", "flowKey": "enrollments" }
  ],
  "scanId": "01KWHRCVJFBBD2AK6W97QFGDYA"
}

Use when: building feature pickers, scoping an agent task to one product area, checking whether a feature exists in the latest scan.


GET /query/feature-display-titles

Returns: { "<featureId>": "<human label>", … }

Use when: rendering user-facing names; keys are the same ids as /query/features.


GET /query/feature?featureId=<id>

Returns: NormalizedGraphResponse — feature metadata + 1-hop subgraph.

json
{
  "queryType": "feature_graph",
  "feature": { "id": "feature:…", "name": "…", "flowKey": "…" },
  "summary": { "implementationAnchors": ["repo:…|Service:…"] },
  "nodes": [  ],
  "edges": [  ],
  "implementationAnchors": [  ],
  "sharedNodes": [],
  "missingSegments": []
}

Use when: explaining how a feature is wired in code, finding entry routes/endpoints, preparing a change plan scoped to one feature.

Agent tips:

  • implementationAnchors — start here for “where is this implemented?”
  • missingSegments — gaps the resolver could not close (stale YAML, missing repo in scan)
  • Follow USES edges from the feature node outward to reach concrete Method / ApiEndpoint nodes

GET /query/repo-graph?repoKey=<key>

Returns: { queryType: "repo_graph", repoKey, nodes, edges, scanId }

Use when: the task is repo-scoped (e.g. “review ng-access-service”), or the full workspace graph is unnecessarily large.


GET /query/technical-graph

Returns: Full workspace graph for the latest scan.

Use loadTechnicalGraphFromQueryResponse() from @helix/shared — it handles the response shape and returns { nodes, edges, repos? }.

Use when: cross-repo analysis, global search by label, building custom traversals.

Avoid when: a repo or feature endpoint suffices — smaller responses are faster and easier to reason about.

Optional: ?inline=1 forces inline JSON when supported (mainly for debugging).


POST /query/compare-features

Body: { "featureA": "<id>", "featureB": "<id>" }

Returns: { queryType: "feature_compare", featureA, featureB, nodes, edges, sharedNodeIds, uniqueToA, uniqueToB }

Use when: deduplicating work, finding shared services between features, spotting unintended coupling.

Agent tips:

  • sharedNodeIds — candidates for careful regression testing when changing either feature
  • uniqueToA / uniqueToB — safe-ish isolation boundaries for refactors

POST /query/impact

Body: { "nodeId": "<graph node id>" }

Returns:

json
{
  "nodeId": "repo:…|Method:…",
  "impactedFeatures": ["feature:…"],
  "impactedRoutes": [],
  "impactedEndpoints": [],
  "impactedSharedNodes": []
}

Use when: before editing a method/service — list features that USE this node.

Agent tips:

  • Non-empty impactedFeatures → warn the user and suggest running tests / reviewing those feature subgraphs
  • Combine with /query/feature on each impacted id for a concrete change checklist

POST /query/node

Body: { "nodeId": "<id>" }

Returns: { node, neighbours: string[] } or 404 { error: "node_not_found" }

Use when: incremental graph exploration without downloading the full graph.

Agent tips:

  • BFS/DFS from an ApiEndpoint or Method using repeated /query/node calls
  • Prefer this over loading /query/technical-graph when depth is bounded (≤ 3 hops)

POST /query/implementation-anchor

Body: { "featureQuery": "<search string>", "flowKey?": "<optional>" }

Returns:

json
{
  "resolved": true,
  "existingAnchors": ["repo:…|Service:…"],
  "recommendedInsertions": [],
  "supportingGraphNodeIds": ["repo:…|Service:…"]
}

When unresolved, recommendedInsertions may contain placeholder suggestions (deterministic stub — verify against real repo layout).

Use when: “where should this logic live?” — pair graph anchors with your own file search.


AI artifact endpoints

All are lazy S3 reads404 if the helix-agent pass has not produced that artifact yet.

EndpointQuery paramContent
GET /query/feature-insightsfeatureIdNarrative insights, structured bullets
GET /query/endpoint-qaendpointIdBackend endpoint Q&A
GET /query/endpoint-potential-issuesendpointIdBackend risk notes
GET /query/endpoint-qa-feclientCallIdFrontend client-call Q&A
GET /query/endpoint-potential-issues-feclientCallIdFrontend risk notes

Use when: enriching human-facing explanations or flagging review items — not as sole evidence (always cross-check graph nodes and source files).

Agent tips on 404:

  • Artifact missing → say “no AI pass yet” and fall back to graph structure
  • Suggest re-running scan + helix-agent for that repo if insights are required

Agent playbooks

“Explain how feature X works”

  1. GET /query/features — resolve exact featureId if the user gave a fuzzy name
  2. GET /query/feature-display-titles — optional friendly name
  3. GET /query/feature?featureId= — structural answer from nodes/edges
  4. GET /query/feature-insights?featureId= — optional narrative layer
  5. Trace ApiEndpoint / CALLS_REMOTE / CALLS chains; cite filePath on each node

“What breaks if I change this method?”

  1. Identify nodeId (from repo-graph or feature subgraph)
  2. POST /query/impact with { nodeId }
  3. For each impactedFeatures[], GET /query/feature?featureId=
  4. Recommend: tests covering those features, review of shared Service/Method nodes

“Find the backend for this UI action”

  1. GET /query/repo-graph?repoKey=<frontend-repo>
  2. Locate ApiClientCall nodes (or search by path/name in nodes)
  3. Follow CALLS_REMOTE edges to ApiEndpoint in backend repos
  4. Optional: GET /query/endpoint-qa-fe?clientCallId= and GET /query/endpoint-qa?endpointId=

“Suggest a fix / improvement”

Combine evidence layers:

SignalSource
Structure/query/feature, /query/repo-graph, /query/node
Blast radius/query/impact
Documented risks/query/endpoint-potential-issues*
Behaviour Q&A/query/endpoint-qa*
Product context/query/feature-insights

Recommendations should reference concrete node ids and file paths. If missingSegments is non-empty or no CALLS_REMOTE exists where expected, say the graph gap explicitly (missing repo in scan, bridge not resolved, stale feature YAML) rather than inventing wiring.


Errors and limits

StatusMeaningAgent action
401Missing/invalid tokenRefresh Cognito ID token
404Unknown node or missing AI artifactVerify id from /query/features or repo-graph; for AI, note artifact not generated
502Lambda failureRetry; check scan is READY
HTML bodyWrong method or path hit SPAUse GET with query params on documented routes

CloudFront may cache GET responses briefly — if a new scan just finished, prefer checking scanId in the response.


Local development

bash
HELIX_GRAPH_PATH="$(pwd)/scans/latest/reports/technical-graph.json" npm run dev:api
curl -sS http://localhost:8787/query/features

No auth when COGNITO_USER_POOL_ID is unset. See Local development.


Implementation reference

ConcernLocation
Route handlersbackend/src/routes.ts
Request schemasshared/src/queries.ts
Graph typesshared/src/graph.ts
HTTP clientshared/src/helixQueryClient.ts
Graph loader helpershared/src/technicalGraphDelivery.ts

For AWS service discovery (SSM params, helix-aws): Other AWS Apps Integration.

Helix Flowgraph — Igentify