curl --request POST \
--url https://api.matproof.com/v1/findings \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"type": "soc2",
"content": "The uploaded evidence does not clearly show the Organization Name or URL.",
"taskId": "tsk_abc123",
"severity": "medium",
"templateId": "fnd_t_abc123",
"dueDate": "2026-03-15T00:00:00.000Z"
}
'import requests
url = "https://api.matproof.com/v1/findings"
payload = {
"type": "soc2",
"content": "The uploaded evidence does not clearly show the Organization Name or URL.",
"taskId": "tsk_abc123",
"severity": "medium",
"templateId": "fnd_t_abc123",
"dueDate": "2026-03-15T00:00:00.000Z"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
type: 'soc2',
content: 'The uploaded evidence does not clearly show the Organization Name or URL.',
taskId: 'tsk_abc123',
severity: 'medium',
templateId: 'fnd_t_abc123',
dueDate: '2026-03-15T00:00:00.000Z'
})
};
fetch('https://api.matproof.com/v1/findings', 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.matproof.com/v1/findings",
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' => 'soc2',
'content' => 'The uploaded evidence does not clearly show the Organization Name or URL.',
'taskId' => 'tsk_abc123',
'severity' => 'medium',
'templateId' => 'fnd_t_abc123',
'dueDate' => '2026-03-15T00:00:00.000Z'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.matproof.com/v1/findings"
payload := strings.NewReader("{\n \"type\": \"soc2\",\n \"content\": \"The uploaded evidence does not clearly show the Organization Name or URL.\",\n \"taskId\": \"tsk_abc123\",\n \"severity\": \"medium\",\n \"templateId\": \"fnd_t_abc123\",\n \"dueDate\": \"2026-03-15T00:00:00.000Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.matproof.com/v1/findings")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"soc2\",\n \"content\": \"The uploaded evidence does not clearly show the Organization Name or URL.\",\n \"taskId\": \"tsk_abc123\",\n \"severity\": \"medium\",\n \"templateId\": \"fnd_t_abc123\",\n \"dueDate\": \"2026-03-15T00:00:00.000Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.matproof.com/v1/findings")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"soc2\",\n \"content\": \"The uploaded evidence does not clearly show the Organization Name or URL.\",\n \"taskId\": \"tsk_abc123\",\n \"severity\": \"medium\",\n \"templateId\": \"fnd_t_abc123\",\n \"dueDate\": \"2026-03-15T00:00:00.000Z\"\n}"
response = http.request(request)
puts response.read_bodyCreate a finding
Push a finding from an external scanner, audit, or custom check into Matproof’s unified Findings view.
curl --request POST \
--url https://api.matproof.com/v1/findings \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"type": "soc2",
"content": "The uploaded evidence does not clearly show the Organization Name or URL.",
"taskId": "tsk_abc123",
"severity": "medium",
"templateId": "fnd_t_abc123",
"dueDate": "2026-03-15T00:00:00.000Z"
}
'import requests
url = "https://api.matproof.com/v1/findings"
payload = {
"type": "soc2",
"content": "The uploaded evidence does not clearly show the Organization Name or URL.",
"taskId": "tsk_abc123",
"severity": "medium",
"templateId": "fnd_t_abc123",
"dueDate": "2026-03-15T00:00:00.000Z"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
type: 'soc2',
content: 'The uploaded evidence does not clearly show the Organization Name or URL.',
taskId: 'tsk_abc123',
severity: 'medium',
templateId: 'fnd_t_abc123',
dueDate: '2026-03-15T00:00:00.000Z'
})
};
fetch('https://api.matproof.com/v1/findings', 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.matproof.com/v1/findings",
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' => 'soc2',
'content' => 'The uploaded evidence does not clearly show the Organization Name or URL.',
'taskId' => 'tsk_abc123',
'severity' => 'medium',
'templateId' => 'fnd_t_abc123',
'dueDate' => '2026-03-15T00:00:00.000Z'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.matproof.com/v1/findings"
payload := strings.NewReader("{\n \"type\": \"soc2\",\n \"content\": \"The uploaded evidence does not clearly show the Organization Name or URL.\",\n \"taskId\": \"tsk_abc123\",\n \"severity\": \"medium\",\n \"templateId\": \"fnd_t_abc123\",\n \"dueDate\": \"2026-03-15T00:00:00.000Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.matproof.com/v1/findings")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"soc2\",\n \"content\": \"The uploaded evidence does not clearly show the Organization Name or URL.\",\n \"taskId\": \"tsk_abc123\",\n \"severity\": \"medium\",\n \"templateId\": \"fnd_t_abc123\",\n \"dueDate\": \"2026-03-15T00:00:00.000Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.matproof.com/v1/findings")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"soc2\",\n \"content\": \"The uploaded evidence does not clearly show the Organization Name or URL.\",\n \"taskId\": \"tsk_abc123\",\n \"severity\": \"medium\",\n \"templateId\": \"fnd_t_abc123\",\n \"dueDate\": \"2026-03-15T00:00:00.000Z\"\n}"
response = http.request(request)
puts response.read_bodyCommon use cases
- Custom security scanner — pipe results from a scanner that isn’t on the integrations list (Trivy, Grype, custom SAST)
- CI/CD pipeline — fail-the-build checks generate findings that are tracked through to remediation
- Manual escalation — issues raised in board / management meetings logged formally
- Bridging external GRC — mirror findings from a parent-org GRC tool into a subsidiary’s Matproof tenant
Idempotency
Always sendIdempotency-Key on POST /v1/findings — most use cases retry on transient failure, and you don’t want duplicate findings:
curl -X POST https://api.matproof.com/v1/findings \
-H "X-API-Key: ..." \
-H "Idempotency-Key: aikido-issue-12345-2026-05-08" \
-H "Content-Type: application/json" \
-d '{
"title": "Vulnerable npm package: lodash@4.17.20",
"severity": "high",
"source": "external-scanner",
"description": "CVE-2021-23337 affects production builds. Fix: upgrade to lodash@4.17.21+",
"linkedControlIds": ["ctrl_iso27001_a8_8"]
}'
Idempotency-Key should encode the originating system’s stable identifier — for the Aikido example above, aikido-issue-{aikido_issue_id} — so retries always resolve to the same Matproof finding.
Linked controls
WhenlinkedControlIds is provided, the finding immediately appears on those controls’ Findings tabs and contributes to the framework’s compliance-score calculation. Multiple controls can be linked when a single finding affects multiple frameworks.
Severity values
informational / low / medium / high / critical
For external scanners, map their severity scale to Matproof’s: most scanners use 0–10 CVSS, where 7+ → high and 9+ → critical.
Response
On success, the response includes the created finding’sid. Store this in your originating system to support future updates (PATCH /v1/findings/{id}) — for example, when the underlying scanner reports the issue resolved.Authorizations
Organisation API key. Generate one in the app under Settings, then API keys. Keys are stored hashed, so the plaintext is shown once.
Headers
Organization ID (required for session auth, optional for API key auth)
Body
Finding data
Type of finding (SOC 2, ISO 27001, DORA, GDPR, HIPAA, PCI DSS, NIS 2)
soc2, iso27001, dora, gdpr, hipaa, pci_dss, nis2 Finding content/message
5000"The uploaded evidence does not clearly show the Organization Name or URL."
Task ID this finding is associated with. Provide exactly one of taskId or scope.
"tsk_abc123"
People-area scope for findings not tied to a task (e.g. people directory, devices tab). Provide exactly one of taskId or scope.
people, people_tasks, people_devices, people_chart, security Finding severity level
critical, high, medium, low, informational ISO 27001 / SOC 2 audit-finding classification (auditor-set; distinct from severity)
major_nonconformity, minor_nonconformity, observation, opportunity_for_improvement, not_applicable Finding template ID (optional)
"fnd_t_abc123"
Due date for finding resolution (ISO 8601)
"2026-03-15T00:00:00.000Z"
Response
The created finding
Was this page helpful?