List controls
Returns controls for the authenticated tenant.
Default items include identifiers, domain, grouping, scope, computed compliance status, and owners.
When frameworkIds is set, status and percentage are computed in that framework set.
Request extra columns with fields (comma-separated).
List responses are a JSON array in data. There is no cursor pagination on this endpoint.
Requires scope control:read or control:write.
curl -X GET "https://api.scrut.io/v1/controls?status=compliant%2Cnon_compliant&frameworkIds=14c4c45d-6c31-4097-a02a-ad9cfd04850e%2C3a10a604-b942-43e5-8294-d418a0448ee5&entityIds=8fa88e7b-eb16-4999-854a-2f407958740a&assigneeEmails=alex%40example.com%2Calex%40example.com&domains=Logical%20and%20Physical%20Access%20Controls&functionGroupings=protect%2Cdetect&controlScope=in_scope&fields=mappedFrameworkIds%2CoutOfScopeReason%2CmarkedOutOfScopeBy" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN (JWT)"
import requests
import json
url = "https://api.scrut.io/v1/controls?status=compliant%2Cnon_compliant&frameworkIds=14c4c45d-6c31-4097-a02a-ad9cfd04850e%2C3a10a604-b942-43e5-8294-d418a0448ee5&entityIds=8fa88e7b-eb16-4999-854a-2f407958740a&assigneeEmails=alex%40example.com%2Calex%40example.com&domains=Logical%20and%20Physical%20Access%20Controls&functionGroupings=protect%2Cdetect&controlScope=in_scope&fields=mappedFrameworkIds%2CoutOfScopeReason%2CmarkedOutOfScopeBy"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN (JWT)"
}
response = requests.get(url, headers=headers)
print(response.json())
const response = await fetch("https://api.scrut.io/v1/controls?status=compliant%2Cnon_compliant&frameworkIds=14c4c45d-6c31-4097-a02a-ad9cfd04850e%2C3a10a604-b942-43e5-8294-d418a0448ee5&entityIds=8fa88e7b-eb16-4999-854a-2f407958740a&assigneeEmails=alex%40example.com%2Calex%40example.com&domains=Logical%20and%20Physical%20Access%20Controls&functionGroupings=protect%2Cdetect&controlScope=in_scope&fields=mappedFrameworkIds%2CoutOfScopeReason%2CmarkedOutOfScopeBy", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN (JWT)"
}
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://api.scrut.io/v1/controls?status=compliant%2Cnon_compliant&frameworkIds=14c4c45d-6c31-4097-a02a-ad9cfd04850e%2C3a10a604-b942-43e5-8294-d418a0448ee5&entityIds=8fa88e7b-eb16-4999-854a-2f407958740a&assigneeEmails=alex%40example.com%2Calex%40example.com&domains=Logical%20and%20Physical%20Access%20Controls&functionGroupings=protect%2Cdetect&controlScope=in_scope&fields=mappedFrameworkIds%2CoutOfScopeReason%2CmarkedOutOfScopeBy", nil)
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN (JWT)")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://api.scrut.io/v1/controls?status=compliant%2Cnon_compliant&frameworkIds=14c4c45d-6c31-4097-a02a-ad9cfd04850e%2C3a10a604-b942-43e5-8294-d418a0448ee5&entityIds=8fa88e7b-eb16-4999-854a-2f407958740a&assigneeEmails=alex%40example.com%2Calex%40example.com&domains=Logical%20and%20Physical%20Access%20Controls&functionGroupings=protect%2Cdetect&controlScope=in_scope&fields=mappedFrameworkIds%2CoutOfScopeReason%2CmarkedOutOfScopeBy')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN (JWT)'
response = http.request(request)
puts response.body
{
"data": [
{
"controlId": "8d7c6b5a-4e3f-4210-9a8b-7c6d5e4f3a2b",
"controlCode": "CC6.1",
"controlName": "Logical access",
"controlDomain": "Logical and Physical Access Controls",
"functionGrouping": "govern",
"controlScope": "out_of_scope",
"status": "non_compliant",
"controlCompliancePercentage": 40,
"assignees": [
{
"name": "Alex Rivera",
"email": "alex@example.com",
"isPrimary": true
}
],
"entities": [
{
"entityId": "8fa88e7b-eb16-4999-854a-2f407958740a",
"entityName": "Organization Wide"
}
],
"mappedFrameworkIds": [
"14c4c45d-6c31-4097-a02a-ad9cfd04850e"
],
"outOfScopeReason": "This control does not apply to the selected entity.",
"markedOutOfScopeBy": {
"name": "Alex Rivera",
"email": "alex@example.com"
},
"addedBy": {
"name": "Alex Rivera",
"email": "alex@example.com"
},
"addedOn": 1704067200000,
"lastModifiedBy": {
"name": "Alex Rivera",
"email": "alex@example.com"
},
"modifiedOn": 1704067200000
}
],
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "validation_failed",
"message": "Request validation failed.",
"details": [
{
"field": "status",
"message": "status contains unknown value(s): unknown"
}
]
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "unauthorized",
"message": "Missing, malformed, or invalid Bearer token.",
"details": []
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "token_revoked",
"message": "The API credential was revoked.",
"details": []
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "token_stale",
"message": "The access token is stale; obtain a new token.",
"details": []
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "forbidden",
"message": "Insufficient scope.",
"details": []
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "not_found",
"message": "The requested resource was not found.",
"details": []
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded.",
"details": [
{
"retryAfterSec": 12
}
]
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "internal_error",
"message": "An unexpected error occurred.",
"details": []
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
{
"error": {
"code": "upstream_unavailable",
"message": "Upstream service is unavailable.",
"details": [
{
"dependency": "frameworks",
"issue": "Failed to process frameworks."
}
]
},
"meta": {
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}
}
/v1/controls
Target server for requests. Edit to use your own host.
Machine access token from POST /oauth/token. Send Authorization: Bearer $SCRUT_ACCESS_TOKEN on every /v1 request.
POST /oauth/token. Send Authorization: Bearer $SCRUT_ACCESS_TOKEN on every /v1 request.Filter by computed control compliance status. Pass a comma-separated list (no spaces required). Allowed values: non_compliant, compliant, not_applicable.
Filter to resources mapped to these framework IDs. Pass a comma-separated list (no spaces required).
Filter to resources linked to these entity (product) IDs. Pass a comma-separated list (no spaces required).
Filter by assignee email addresses. Matches any assignees[].email. URL-encode + in plus-addressed emails as %2B. Pass a comma-separated list (no spaces required).
Filter by control domain name. Match is case-insensitive. Pass a comma-separated list (no spaces required).
Filter by NIST-style function grouping. Pass a comma-separated list (no spaces required). Allowed values: govern, identify, protect, detect, respond, recover.
Filter by control scope. Pass a comma-separated list (no spaces required). Allowed values: out_of_scope, in_scope.
Additional list columns. Default list items omit these keys until requested. Pass a comma-separated list (no spaces required). Allowed values: mappedFrameworkIds, outOfScopeReason, markedOutOfScopeBy, addedBy, addedOn, lastModifiedBy, modifiedOn.
Request Preview
Response
Response will appear here after sending the request
Authentication
Bearer token (JWT). Machine access token from POST /oauth/token. Send Authorization: Bearer $SCRUT_ACCESS_TOKEN on every /v1 request.
Query Parameters
Filter by computed control compliance status. Pass a comma-separated list (no spaces required). Allowed values: non_compliant, compliant, not_applicable.
compliant,non_compliantFilter to resources mapped to these framework IDs. Pass a comma-separated list (no spaces required).
14c4c45d-6c31-4097-a02a-ad9cfd04850e,3a10a604-b942-43e5-8294-d418a0448ee5Filter to resources linked to these entity (product) IDs. Pass a comma-separated list (no spaces required).
8fa88e7b-eb16-4999-854a-2f407958740aFilter by assignee email addresses. Matches any assignees[].email. URL-encode + in plus-addressed emails as %2B. Pass a comma-separated list (no spaces required).
alex@example.com,alex@example.comFilter by control domain name. Match is case-insensitive. Pass a comma-separated list (no spaces required).
Logical and Physical Access ControlsFilter by NIST-style function grouping. Pass a comma-separated list (no spaces required). Allowed values: govern, identify, protect, detect, respond, recover.
protect,detectFilter by control scope. Pass a comma-separated list (no spaces required). Allowed values: out_of_scope, in_scope.
in_scopeAdditional list columns. Default list items omit these keys until requested. Pass a comma-separated list (no spaces required). Allowed values: mappedFrameworkIds, outOfScopeReason, markedOutOfScopeBy, addedBy, addedOn, lastModifiedBy, modifiedOn.
mappedFrameworkIds,outOfScopeReason,markedOutOfScopeBy