Register control review
Stores a review of the subject as a governance statement in the project's graph, with a verifiable credential signed for the caller, and links it to the control it reviews. The caller needs create_comments on the project, and submittedBy must be the caller's DID.
https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}curl --request POST \
--url 'https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}' \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{"attachmentCid":"[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]","controlCid":"urn:cid:cotrol_cid","declarationCid":"[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]","documentType":"string","extra":{"key":null},"outcome":"PASSED","statement":"Audit Review message","subjectLine":"Review of control","submittedAt":"2025-03-12T12:00:06Z","submittedBy":"did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"}'const response = await fetch("https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
})
});
const data = await response.json();interface StatementResponse {
documentCid: string;
statement: Record<string, unknown>;
statementCid: string;
}
const response = await fetch("https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
})
});
if (!response.ok) throw new Error(`${response.status} ${response.statusText}`);
const data: StatementResponse = await response.json();import requests
response = requests.post(
"https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}",
headers={
"Authorization": "Bearer <token>",
"Content-Type": "application/json",
},
json={
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": None,
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1",
},
)
response.raise_for_status()
print(response.json())package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
}`)
req, err := http.NewRequest(http.MethodPost, "https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer <token>")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
fmt.Println(res.Status, string(data))
}import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}"))
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"attachmentCid": "[\\"urn:cid:attachment_cid_one\\", \\"urn:cid:attachment_cid_two\\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\\"urn:cid:declaration_one\\", \\"urn:cid:declaration_two\\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
}
"""))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, "https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "<token>");
request.Content = new StringContent("""
{
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
}
""", Encoding.UTF8, "application/json");
using var response = await client.SendAsync(request);
Console.WriteLine($"{(int)response.StatusCode} {await response.Content.ReadAsStringAsync()}");<?php
$ch = curl_init('https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Authorization: Bearer <token>',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => <<<'JSON'
{
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
}
JSON,
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
echo $status . " " . $response . PHP_EOL;require "net/http"
uri = URI("https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer <token>"
request["Content-Type"] = "application/json"
request.body = <<~'JSON'
{
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
}
JSON
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
http.request(request)
end
puts "#{response.code} #{response.body}"// Cargo.toml dependencies: reqwest (features "json"), serde_json, tokio (features "full")
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let response = reqwest::Client::new()
.post("https://<host>/gov/v1/controls/review/{subject_cid}/{project_uuid}")
.header("Authorization", "Bearer <token>")
.json(&json!({
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
}))
.send()
.await?;
println!("{} {}", response.status(), response.text().await?);
Ok(())
}Authorizations
BearerAuth· HTTP bearer (JWT)
Parameters
Path parameters
| Name | Type | Description |
|---|---|---|
subject_cidrequired | string | Subject CID |
project_uuidrequired | string | Project UUID |
Request bodyrequired
attachmentCidstring[] | nullcontrolCidstringrequireddeclarationCidstring[] | nulldocumentTypestringextraobject | nullShow properties
Map of
anyoutcomestring | nullstatementstring | nullsubjectLinestring | nullsubmittedAtstring<date-time>requiredDefault
"2025-03-12T12:00:06Z"submittedBystringrequired
{
"attachmentCid": "[\"urn:cid:attachment_cid_one\", \"urn:cid:attachment_cid_two\"]",
"controlCid": "urn:cid:cotrol_cid",
"declarationCid": "[\"urn:cid:declaration_one\", \"urn:cid:declaration_two\"]",
"documentType": "string",
"extra": {
"key": null
},
"outcome": "PASSED",
"statement": "Audit Review message",
"subjectLine": "Review of control",
"submittedAt": "2025-03-12T12:00:06Z",
"submittedBy": "did:key:z6MkvWwG4YJDNEBq6ufypq6mBGpKje7bfJefcQkMoGWPjoq1"
}Responses
200Governance statement created for the review
documentCidstringrequiredstatementGovernanceStatementrequiredRecords governance information for a subject This statement type associates governance documents (policies, procedures, compliance documents) with subjects in the lineage system.
Show GovernanceStatement
@contextstringrequiredJSON-LD context URL
@idstringrequiredUnique identifier for this statement
@typestringrequiredStatement type identifier
documentstringrequiredCID of the governance document
registeredBystringrequiredDID of the entity that registered this statement
subjectstringrequiredThe subject to which governance applies
timestampstringrequiredISO 8601 timestamp of when the statement was created
statementCidstringrequired
{
"documentCid": "string",
"statement": {
"@context": "string",
"@id": "string",
"@type": "string",
"document": "string",
"registeredBy": "string",
"subject": "string",
"timestamp": "string"
},
"statementCid": "string"
}400The project UUID does not parse
callstackobjectShow properties
object | nullerrorstringrequired
{
"callstack": {},
"error": "string"
}401Missing or invalid bearer token, or submittedBy is not the caller's DID
callstackobjectShow properties
object | nullerrorstringrequired
{
"callstack": {},
"error": "string"
}403Caller lacks create_comments on the project
callstackobjectShow properties
object | nullerrorstringrequired
{
"callstack": {},
"error": "string"
}500Internal error
callstackobjectShow properties
object | nullerrorstringrequired
{
"callstack": {},
"error": "string"
}503Auth Service or blob storage unavailable
callstackobjectShow properties
object | nullerrorstringrequired
{
"callstack": {},
"error": "string"
}