Query API reference
Call query API endpoints to execute query runs against your HCP Terraform workspaces. Query runs retrieve information about workspace resources and configurations. They are asynchronous operations that you can monitor for status and results.
Overview
The scope of the API includes the following endpoints:
| Method | Path | Action |
|---|---|---|
POST | /queries | Call this endpoint to create a query run. |
GET | /workspaces/:workspace_id/queries | Call this endpoint to list query runs for a workspace. |
GET | /queries/:query_id | Call this endpoint to show a query run. |
POST | /queries/:query_id/actions/cancel | Call this endpoint to cancel a query run. |
Create a query run
This endpoint creates a new query run.
POST /queries
| Status | Response | Reason |
|---|---|---|
| 201 | JSON API document | Successfully created a query run. |
| 404 | JSON API error object | Not found or the user is unauthorized to perform this action. |
| 422 | JSON API error object | Malformed request body, such as missing attributes and wrong types. |
| 500 | JSON API error object | Internal system failure. |
Request body
This POST endpoint requires a JSON object with the following properties as a request payload.
Properties without a default value are required.
| Key path | Type | Default | Description |
|---|---|---|---|
data.type | string | Must be "queries". | |
data.attributes.source | string | The source of the query. Use "tfe-api" for API requests. Query definitions come from the configuration version. | |
data.attributes.generate-config-out | boolean | true | Specifies whether the Terraform CLI execution passes the -generate-config-out flag during the query run. |
data.attributes.variables | array[{key, value}] | (empty array) | Specifies an optional list of run-specific variable values. Refer to run-specific variables for details. |
data.relationships.workspace.data.type | string | Must be "workspaces". | |
data.relationships.workspace.data.id | string | The ID of the workspace to run the query against. | |
data.relationships.configuration-version.data.type | string | Must be "configuration-versions". | |
data.relationships.configuration-version.data.id | string | The ID of the configuration version to use for the query. |
For policy evaluation in HCP Terraform, the request also supports the following optional attributes:
| Key path | Type | Default | Description |
|---|---|---|---|
data.attributes.policy-evaluation-opt-in | boolean | true | Controls automatic workspace policy evaluation. Defaults to true for every query source. Set to false to suppress automatic workspace policies when query policy opt-out is enabled. |
data.attributes.policy-paths | array of strings | (empty array) | Explicit policy source paths in the uploaded configuration. These paths are independent of the automatic workspace policy preference. Refer to Explicit policy paths. |
Policy evaluation
Policy evaluation requires a workspace that uses Terraform v1.17.0 or later with remote or agent execution. Resource discovery alone requires Terraform v1.14.0 or later. Your organization must have Terraform policy and search policy evaluation enabled, including access to policy enforcement and versioned policy sets. The execution environment must have a compatible Terraform policy runtime. Refer to Search policy requirements.
Automatic evaluation uses applicable Terraform policy (tfpolicy) policy sets, including workspace assignments, inherited project assignments, and organization-wide assignments. HCP Terraform does not support automatic policy evaluation for Sentinel and OPA policy sets. Refer to Policy set configuration.
For API queries, policy evaluation requires generate-config-out to be true. Terraform evaluates configuration generated from full resource data; identities alone are insufficient. Setting include_resource = true in a query definition does not replace the API's generated-configuration requirement. Additional resource reads can increase query duration.
Leave policy-evaluation-opt-in omitted to use default evaluation. To query without generated configuration, set both generate-config-out and policy-evaluation-opt-in to false. Explicit opt-out suppresses automatic workspace policies; it does not suppress policies supplied through policy-paths.
If no applicable Terraform policy sets exist and you provide no explicit policy paths, HCP Terraform will not evaluate any policies against the workspace. An absent evaluation is not a passing result. Query-time results are informational and do not block import or replace plan-time enforcement.
Explicit policy paths
Use policy-paths to select policy set directories included in the configuration uploaded for remote execution, for example ["policies/security", "policies/tagging"]. These are server-side relative paths, not paths to files on your workstation. Each path must:
- Contain between 1 and 255 characters.
- Use only letters, numbers, periods, underscores, dashes, and forward slashes.
- Not start or end with a forward slash or contain
...
Explicit paths select policy sources separately from automatic workspace assignments. API policy evaluation still requires generated configuration.
Sample Payload
This request omits policy-evaluation-opt-in, so HCP Terraform evaluates applicable Terraform policy sets by default when the policy prerequisites are met.
{
"data": {
"type": "queries",
"attributes": {
"source": "tfe-api",
"generate-config-out": true,
"variables": [
{ "key": "replicas", "value": "2" }
]
},
"relationships": {
"workspace": {
"data": {
"type": "workspaces",
"id": "ws-ABC123"
}
},
"configuration-version": {
"data": {
"type": "configuration-versions",
"id": "cv-XYZ789"
}
}
}
}
}
Sample Request
$ curl\
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
--data @payload.json \
https://app.terraform.io/api/v2/queries
Sample Payload with policy opt-out
Submit this payload to the same POST /api/v2/queries endpoint to generate configuration without evaluating automatic workspace policies:
{
"data": {
"type": "queries",
"attributes": {
"source": "tfe-api",
"generate-config-out": true,
"policy-evaluation-opt-in": false
},
"relationships": {
"workspace": {
"data": { "type": "workspaces", "id": "ws-ABC123" }
},
"configuration-version": {
"data": { "type": "configuration-versions", "id": "cv-XYZ789" }
}
}
}
}
Policy validation errors
When query policy opt-out is enabled, policy-evaluation-opt-in must be a Boolean. For example, supplying the string "false" instead of the Boolean false returns HTTP 422:
{
"errors": [
{
"status": "422",
"title": "invalid attributes",
"detail": "Policy evaluation opt in must be a boolean"
}
]
}
A policy preference of true with generate-config-out: false also fails validation for API queries because policy evaluation requires generated configuration. Omission uses the default preference of true.
Sample Response
{
"data": {
"id": "query-ABC123",
"type": "queries",
"attributes": {
"created-at": "2025-01-15T10:30:00.000Z",
"source": "tfe-api",
"generate-config-out": true,
"resources-discovered": 0,
"variables": [
{ "key": "replicas", "value": "2" }
],
"status-timestamps": {
"pending-at": "2025-01-15T10:30:00.000Z"
},
"status": "pending",
"log-read-url": "https://archivist.terraform.io/v1/object/..."
},
"relationships": {
"workspace": {
"data": {
"type": "workspaces",
"id": "ws-ABC123"
}
},
"configuration-version": {
"data": {
"type": "configuration-versions",
"id": "cv-XYZ789"
}
},
"created-by": {
"data": {
"type": "users",
"id": "user-123"
}
}
},
"links": {
"self": "/api/v2/queries/query-ABC123"
}
}
}
List query runs for a workspace
This endpoint lists query runs for a particular workspace.
GET /workspaces/:workspace_id/queries
| Parameter | Description |
|---|---|
:workspace_id | The ID of the workspace to list query runs for. |
Query parameters
This endpoint supports pagination with standard URL query parameters. You must use percent-style encoding [ as %5B and ] as %5D if your tooling doesn't automatically encode URLs.
| Parameter | Description |
|---|---|
page[number] | Optional. If omitted, the endpoint returns the first page. |
page[size] | Optional. If omitted, the endpoint returns 20 query runs per page. |
| Status | Response | Reason |
|---|---|---|
| 200 | JSON API document | Successfully retrieved the list of query runs. |
| 404 | JSON API error object | Not found or the user is unauthorized to perform this action. |
Sample Request
$ curl\
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
https://app.terraform.io/api/v2/workspaces/ws-ABC123/queries
Sample Response
{
"data": [
{
"id": "query-ABC123",
"type": "queries",
"attributes": {
"created-at": "2025-01-15T10:30:00.000Z",
"source": "tfe-api",
"generate-config-out": true,
"resources-discovered": 5,
"variables": [
{ "key": "replicas", "value": "2" }
],
"status-timestamps": {
"pending-at": "2025-01-15T10:30:00.000Z",
"queued-at": "2025-01-15T10:30:05.000Z",
"running-at": "2025-01-15T10:30:10.000Z",
"finished-at": "2025-01-15T10:35:00.000Z"
},
"status": "finished",
"log-read-url": "https://archivist.terraform.io/v1/object/..."
},
"relationships": {
"workspace": {
"data": {
"type": "workspaces",
"id": "ws-ABC123"
}
},
"configuration-version": {
"data": {
"type": "configuration-versions",
"id": "cv-XYZ789"
}
},
"created-by": {
"data": {
"type": "users",
"id": "user-123"
}
}
},
"links": {
"self": "/api/v2/queries/query-ABC123"
}
}
],
"links": {
"self": "https://app.terraform.io/api/v2/workspaces/ws-ABC123/queries?page%5Bnumber%5D=1&page%5Bsize%5D=20",
"first": "https://app.terraform.io/api/v2/workspaces/ws-ABC123/queries?page%5Bnumber%5D=1&page%5Bsize%5D=20",
"prev": null,
"next": null,
"last": "https://app.terraform.io/api/v2/workspaces/ws-ABC123/queries?page%5Bnumber%5D=1&page%5Bsize%5D=20"
},
"meta": {
"pagination": {
"current-page": 1,
"page-size": 20,
"prev-page": null,
"next-page": null,
"total-pages": 1,
"total-count": 1
}
}
}
Show a query run
This endpoint shows details for a specific query run.
GET /queries/:query_id
| Parameter | Description |
|---|---|
:query_id | The ID of the query run to retrieve. |
| Status | Response | Reason |
|---|---|---|
| 200 | JSON API document | Successfully retrieved the query run. |
| 404 | JSON API error object | Not found or the user is unauthorized to perform this action. |
Sample Request
$ curl\
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
https://app.terraform.io/api/v2/queries/query-ABC123
Sample Response
{
"data": {
"id": "query-ABC123",
"type": "queries",
"attributes": {
"created-at": "2025-01-15T10:30:00.000Z",
"source": "tfe-api",
"generate-config-out": true,
"resources-discovered": 5,
"list-completions": [
{
"address": "list.aws_instance.example",
"resource-type": "aws_instance",
"total": 5
}
],
"variables": [
{ "key": "replicas", "value": "2" }
],
"status-timestamps": {
"pending-at": "2025-01-15T10:30:00.000Z",
"queued-at": "2025-01-15T10:30:05.000Z",
"running-at": "2025-01-15T10:30:10.000Z",
"finished-at": "2025-01-15T10:35:00.000Z"
},
"status": "finished",
"log-read-url": "https://archivist.terraform.io/v1/object/..."
},
"relationships": {
"workspace": {
"data": {
"type": "workspaces",
"id": "ws-ABC123"
}
},
"configuration-version": {
"data": {
"type": "configuration-versions",
"id": "cv-XYZ789"
}
},
"created-by": {
"data": {
"type": "users",
"id": "user-123"
}
}
},
"links": {
"self": "/api/v2/queries/query-ABC123"
}
}
}
Cancel a query run
This endpoint cancels a query run that is currently pending or running.
POST /queries/:query_id/actions/cancel
| Parameter | Description |
|---|---|
:query_id | The ID of the query run to cancel. |
| Status | Response | Reason |
|---|---|---|
| 202 | Empty body | Successfully canceled the query run. |
| 409 | JSON API error object | Failed to transition query run to a canceled state. |
Sample Request
$ curl\
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request POST \
https://app.terraform.io/api/v2/queries/query-ABC123/actions/cancel
Query run attributes
Query runs have the following attributes:
Policy attributes
Create, list, and show responses include the persisted policy-evaluation-opt-in preference. When search policy evaluation is enabled for your organization, responses also include policy-paths, which is null when you provide no explicit paths. These attributes describe the preference and explicit sources, not whether evaluation completes or resources pass.
For the default-evaluation request, the response's attributes object includes these additional fields:
{
"policy-evaluation-opt-in": true,
"policy-paths": null
}
For the opt-out request, the persisted preference is false:
{
"policy-evaluation-opt-in": false,
"policy-paths": null
}
Policy results in list completions
The show endpoint includes list-completions for completed list blocks. When Search policy evaluation is enabled, each entry also includes policies-passed and policies-failed:
{
"list-completions": [
{
"address": "list.aws_instance.example",
"resource-type": "aws_instance",
"total": 5,
"policies-passed": 3,
"policies-failed": 1
}
]
}
These counts describe resource-row outcomes, not individual policies. They do not need to add up to total: a resource can have an unknown result, an evaluation error, or no policy targeting the resource type specified by the list block. Missing resource configuration produces an unknown result. The create and list endpoints do not include list-completions.
For detailed policy results and diagnostics, retrieve the existing query log using log-read-url. Query results can be incomplete when generated configuration lacks attributes or relationship data that a policy requires. They do not provide a complete compliance assessment or replace plan-time enforcement.
Status
The status attribute indicates the current state of the query run. Possible values are:
pending: The query run has been created but is not yet queued for execution.running: The query run is currently executing.finished: The query run completed successfully.canceled: The query run was canceled before completion.errored: The query run encountered an error during execution.
Status timestamps
The status-timestamps object contains timestamps for when the query run entered each status:
pending-at: When the query run was created.queued-at: When the query run was queued for execution.running-at: When the query run started executing.finished-at: When the query run completed successfully.errored-at: When the query run encountered an error.canceled-at: When the query run was canceled.
Log read URL
The log-read-url attribute contains a URL to retrieve the logs for the query run.
Available Related Resources
The GET endpoints above can optionally return related resources, if requested with the include query parameter. The following resource types are available:
created-by- The user who created the query run.configuration-version- The configuration version used for the query run.configuration_version.ingress_attributes- The ingress attributes for the configuration version used for the query run.