Run an ad-hoc OpalQuery
curl --request POST \
--url https://api.opal.dev/v1/queries/run \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"type": "NODE",
"query": {
"nodeFilters": {
"entityTypes": [
"RESOURCE"
],
"entityTag": {
"key": "env",
"value": "prod"
}
},
"accessFilters": {
"isAccessibleBy": {
"entityTypes": [
"USER"
],
"entityTag": {
"key": "contractor"
}
}
}
},
"first": 50
}
'import requests
url = "https://api.opal.dev/v1/queries/run"
payload = {
"type": "NODE",
"query": {
"nodeFilters": {
"entityTypes": ["RESOURCE"],
"entityTag": {
"key": "env",
"value": "prod"
}
},
"accessFilters": { "isAccessibleBy": {
"entityTypes": ["USER"],
"entityTag": { "key": "contractor" }
} }
},
"first": 50
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
type: 'NODE',
query: {
nodeFilters: {entityTypes: ['RESOURCE'], entityTag: {key: 'env', value: 'prod'}},
accessFilters: {isAccessibleBy: {entityTypes: ['USER'], entityTag: {key: 'contractor'}}}
},
first: 50
})
};
fetch('https://api.opal.dev/v1/queries/run', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.opal.dev/v1/queries/run",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'type' => 'NODE',
'query' => [
'nodeFilters' => [
'entityTypes' => [
'RESOURCE'
],
'entityTag' => [
'key' => 'env',
'value' => 'prod'
]
],
'accessFilters' => [
'isAccessibleBy' => [
'entityTypes' => [
'USER'
],
'entityTag' => [
'key' => 'contractor'
]
]
]
],
'first' => 50
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.opal.dev/v1/queries/run"
payload := strings.NewReader("{\n \"type\": \"NODE\",\n \"query\": {\n \"nodeFilters\": {\n \"entityTypes\": [\n \"RESOURCE\"\n ],\n \"entityTag\": {\n \"key\": \"env\",\n \"value\": \"prod\"\n }\n },\n \"accessFilters\": {\n \"isAccessibleBy\": {\n \"entityTypes\": [\n \"USER\"\n ],\n \"entityTag\": {\n \"key\": \"contractor\"\n }\n }\n }\n },\n \"first\": 50\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.opal.dev/v1/queries/run")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"NODE\",\n \"query\": {\n \"nodeFilters\": {\n \"entityTypes\": [\n \"RESOURCE\"\n ],\n \"entityTag\": {\n \"key\": \"env\",\n \"value\": \"prod\"\n }\n },\n \"accessFilters\": {\n \"isAccessibleBy\": {\n \"entityTypes\": [\n \"USER\"\n ],\n \"entityTag\": {\n \"key\": \"contractor\"\n }\n }\n }\n },\n \"first\": 50\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.opal.dev/v1/queries/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"NODE\",\n \"query\": {\n \"nodeFilters\": {\n \"entityTypes\": [\n \"RESOURCE\"\n ],\n \"entityTag\": {\n \"key\": \"env\",\n \"value\": \"prod\"\n }\n },\n \"accessFilters\": {\n \"isAccessibleBy\": {\n \"entityTypes\": [\n \"USER\"\n ],\n \"entityTag\": {\n \"key\": \"contractor\"\n }\n }\n }\n },\n \"first\": 50\n}"
response = http.request(request)
puts response.read_body{
"type": "NODE",
"edges": [
{
"node": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"entityItemType": "OPAL_ROLE"
},
"cursor": "<string>"
}
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "<string>",
"hasPreviousPage": true,
"startCursor": "<string>"
}
}Run an ad-hoc OpalQuery
Runs an ad-hoc OpalQuery and returns the results. Currently supports NODE queries (users, resources, groups). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you’d like to be added to the beta.
POST
/
queries
/
run
Run an ad-hoc OpalQuery
curl --request POST \
--url https://api.opal.dev/v1/queries/run \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"type": "NODE",
"query": {
"nodeFilters": {
"entityTypes": [
"RESOURCE"
],
"entityTag": {
"key": "env",
"value": "prod"
}
},
"accessFilters": {
"isAccessibleBy": {
"entityTypes": [
"USER"
],
"entityTag": {
"key": "contractor"
}
}
}
},
"first": 50
}
'import requests
url = "https://api.opal.dev/v1/queries/run"
payload = {
"type": "NODE",
"query": {
"nodeFilters": {
"entityTypes": ["RESOURCE"],
"entityTag": {
"key": "env",
"value": "prod"
}
},
"accessFilters": { "isAccessibleBy": {
"entityTypes": ["USER"],
"entityTag": { "key": "contractor" }
} }
},
"first": 50
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
type: 'NODE',
query: {
nodeFilters: {entityTypes: ['RESOURCE'], entityTag: {key: 'env', value: 'prod'}},
accessFilters: {isAccessibleBy: {entityTypes: ['USER'], entityTag: {key: 'contractor'}}}
},
first: 50
})
};
fetch('https://api.opal.dev/v1/queries/run', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.opal.dev/v1/queries/run",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'type' => 'NODE',
'query' => [
'nodeFilters' => [
'entityTypes' => [
'RESOURCE'
],
'entityTag' => [
'key' => 'env',
'value' => 'prod'
]
],
'accessFilters' => [
'isAccessibleBy' => [
'entityTypes' => [
'USER'
],
'entityTag' => [
'key' => 'contractor'
]
]
]
],
'first' => 50
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.opal.dev/v1/queries/run"
payload := strings.NewReader("{\n \"type\": \"NODE\",\n \"query\": {\n \"nodeFilters\": {\n \"entityTypes\": [\n \"RESOURCE\"\n ],\n \"entityTag\": {\n \"key\": \"env\",\n \"value\": \"prod\"\n }\n },\n \"accessFilters\": {\n \"isAccessibleBy\": {\n \"entityTypes\": [\n \"USER\"\n ],\n \"entityTag\": {\n \"key\": \"contractor\"\n }\n }\n }\n },\n \"first\": 50\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.opal.dev/v1/queries/run")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"NODE\",\n \"query\": {\n \"nodeFilters\": {\n \"entityTypes\": [\n \"RESOURCE\"\n ],\n \"entityTag\": {\n \"key\": \"env\",\n \"value\": \"prod\"\n }\n },\n \"accessFilters\": {\n \"isAccessibleBy\": {\n \"entityTypes\": [\n \"USER\"\n ],\n \"entityTag\": {\n \"key\": \"contractor\"\n }\n }\n }\n },\n \"first\": 50\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.opal.dev/v1/queries/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"NODE\",\n \"query\": {\n \"nodeFilters\": {\n \"entityTypes\": [\n \"RESOURCE\"\n ],\n \"entityTag\": {\n \"key\": \"env\",\n \"value\": \"prod\"\n }\n },\n \"accessFilters\": {\n \"isAccessibleBy\": {\n \"entityTypes\": [\n \"USER\"\n ],\n \"entityTag\": {\n \"key\": \"contractor\"\n }\n }\n }\n },\n \"first\": 50\n}"
response = http.request(request)
puts response.read_body{
"type": "NODE",
"edges": [
{
"node": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"entityItemType": "OPAL_ROLE"
},
"cursor": "<string>"
}
],
"pageInfo": {
"hasNextPage": true,
"endCursor": "<string>",
"hasPreviousPage": true,
"startCursor": "<string>"
}
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
application/json
Request body for running an ad-hoc OpalQuery. The type field determines which query schema applies.
Available options:
NODE The filter body for a NODE-type OpalQuery.
Show child attributes
Show child attributes
Maximum number of results to return. Defaults to 200.
Example:
200
Cursor from a previous response to fetch the next page of results.
Example:
"29827fb8-f2dd-4e80-9576-28e31e9934ac"
Response
200 - application/json
The results of the OpalQuery.
Last modified on July 23, 2026
Was this page helpful?
⌘I