Compliance Reports
A compliance report packages what MITRITY governed over a period into a document you can hand to an auditor: the decisions the platform made, the records behind each figure, and a statement of what the report could not see.
Reports are built from the governance record itself — audit events, approvals, data-loss and injection detections, threat matches, findings, coverage, policies, agents, reviews and attestations. Nothing is entered by hand, and nothing is inferred.
Report types
| Type | What it covers |
|---|---|
soc2 | Enforcement, human oversight, sensitive data, execution coverage, open findings, policies in force |
gdpr | Sensitive data first, then enforcement, human oversight and the agents in scope |
iso27001 | Enforcement, threat intelligence, prompt injection, execution coverage, open findings, policies in force |
executive | Enforcement, human oversight, execution coverage and open findings, for a non-technical reader |
inventory | The agents and policies registered, and the coverage state of each agent |
ai_assessment | Everything on file about one agent — the document you hand an auditor for that agent. Requires subject_agent_id |
framework | One compliance framework, control by control, with the gap list. Requires framework_slug |
Every report, whatever its type, ends with a data integrity section (below).
What a section contains
Each section states its figures, shows a breakdown, and lists the records behind them:
- Enforcement — the actions an enforcement point decided in the period, with the allowed, blocked, held and alerted counts (and timed-out holds, when there are any), which add up to the actions evaluated; the actions a connector observed on a connected platform, stated beside them because nothing gated them; the average drift score; a breakdown of what stopped the actions that were stopped; and the most recent blocked actions.
- Human oversight — the actions held for a person to decide, by outcome, and the requests raised in the period.
- Sensitive data — data-loss detections by action taken, and the most recent detections. A detection names the pattern that matched and how many values were found; it never reproduces the content.
- Prompt injection — detections by action taken, and the highest-scoring content that reached your agents.
- Threat intelligence — matches by severity, and the most recent matches with the indicator that fired.
- Open findings — conformance and runtime findings that are open now, by severity, each with its remediation.
- Execution coverage — how many agents are in each coverage state.
- Policies in force — how many policies decided the actions in the report, how many deny by default, and how each is configured.
- Agents in scope — the agents registered, how many are active, and the mission scope each is governed against.
A section with nothing to report says so. "No injection detections in the period" is a statement an auditor needs; a missing section is not.
Every report counts an agent's actions the same way. An action is something an agent did: a decision an enforcement point made about it, or activity a connector observed on a connected platform. Changes people made through MITRITY are governance records, not agent actions. That covers registering an agent, opening or deciding a review, a lifecycle change and a policy edit. Governance records share the audit trail with the actions and are counted apart, in the data-integrity section. The dashboard's "Actions evaluated" is the same figure the Enforcement section states for the same period.
The AI assessment
An ai_assessment is about one agent, in the order an auditor asks the questions:
- Identity and ownership — the agent, where it runs, who answers for it, and the mission scope it is governed against.
- Use case, criticality and risk tier — how your organization classified the agent and where it stands in the governance lifecycle. A field nobody has set is reported as not classified, never as a pass.
- Assessment — the latest questionnaire submitted about the agent: the template and version it answered, every answer as given, and the advisory score. A questionnaire that was opened and never answered is not a submission: when no questionnaire has been answered, the section names the open one as not yet assessed.
- Attestation and decisions — every decided review, with the attestation text reproduced exactly as the reviewer wrote it.
- Risk register — the risks recorded against the agent in the AI risk register, worst residual risk first: inherent and residual scores on the shared 1–5 likelihood × impact scale, status, mitigations and the MITRITY capabilities behind them, and the owner. An accepted risk shows who accepted it, when, and the sentence they put on the record. An empty register is stated as such, never rendered as a register that looks reviewed.
- Risk and drift — the agent's actions evaluated in the period and what was decided, its actions a connector observed, the average and peak drift score, the actions past the anomaly line (stated against all of the agent's actions, observed ones included), and whether drift rose, fell or held steady over the period. Reviews, lifecycle changes and other changes people made to the agent are not its actions and are not counted here.
- Execution coverage and findings — the coverage state, what the agent's runtime attested about its own configuration, and every finding against the agent from every source: conformance checks, runtime observation, connector posture checks, adversarial testing and model scanning. It lists each finding that is open now, accepted as a risk, or resolved during the period, with its source, severity, status and remediation, and links to where the finding lives. Open findings are counted by severity and by source. A posture check keeps only its current state, so it is listed while the check warns. The report reads up to 500 findings: open ones first, then accepted risks, then resolved ones, the most severe first within each. For an agent with more on file, each figure says how far the read got: exact when every finding in that status was read, "at least" when the read stopped partway through it, and "not counted" when the read never reached it.
- Human oversight — the agent's held actions in the period, pending ones included.
- Policy in force — the policy bound to the agent, or its environment's default, and how it is configured.
- Adversarial testing — the red-team findings against the agent that are open, accepted as a risk, or resolved during the period, with remediation. It counts the same findings the coverage section lists. No findings is stated as not assessed: an absence of findings is not evidence of testing.
- Models — the models the agent called through the LLM Gateway in the period, how those calls were governed, and what the model inventory knows about each, including the open findings and accepted risks from model scanning.
Each section states what it could not see in its own words, and the data-integrity section repeats every such statement in one table.
The framework report
A framework report is one compliance framework from the libraries MITRITY carries — the EU AI Act, the NIST AI RMF, ISO/IEC 42001, ISO/IEC 27001, the GDPR, SOC 2, the OWASP Top 10 for LLM Applications or MITRE ATLAS — read control by control against your organization's computed compliance posture:
- Framework — the framework, the edition of MITRITY's control library it is read through, the attribution and text policy that edition carries, and which of its controls apply to you: in the EU AI Act library your highest declared agent risk tier selects them, and controls out of scope for that tier are listed as such, never counted as failures; in the other libraries every control applies until you record it as not applicable. Control identifiers are stated as published and the attribution says whose the titles are; every summary is MITRITY's own wording, never a quotation of the source text.
- Coverage — how many of the applicable controls MITRITY has assessed and what it found, stated as "N of M applicable controls covered; K not assessed" with a per-category breakdown. Coverage is never a bare percentage: a control MITRITY has not assessed is not assessed, not failed and not passed. The sentence is the same one the Frameworks page prints for the same rows.
- Controls — every control with its state (covered, partially covered, not covered, unknown, not applicable or out of scope), the reason for that state naming the capabilities whose evidence bears on it, who owns it in your organization, and any override a person recorded with its note and date.
- Gap list — the applicable controls you cannot currently show full evidence for, with what would close each gap: the MITRITY capability whose evidence the control maps to and where to find it, or the organizational measure the library says the control needs.
The soc2, gdpr and iso27001 report types are different documents: the fixed sections of the governance record listed in the table above. A framework report on the soc2, gdpr or iso_27001 library reads the framework itself, control by control, with the gap list.
The posture is recomputed before the report is assembled, so a framework report reflects your data as it stands at generation. A framework nothing has been computed for yet says so in the coverage section, the controls table and the data-integrity section.
Generating a report
From the dashboard
- Go to Reports.
- Choose the report type and the period. An AI assessment also asks which agent it is about; a framework report asks which framework.
- Generate. The report appears immediately as queued and updates as it is produced.
From the API
curl -X POST https://api.mitrity.com/api/v1/reports \
-H "Authorization: Bearer mk_your-api-key" \
-H "Content-Type: application/json" \
-d '{
"report_type": "soc2",
"environment_id": "6f9f1f6c-1f5e-4a5b-9a1d-2f3c4d5e6f70",
"period_start": "2026-01-01T00:00:00Z",
"period_end": "2026-03-01T00:00:00Z",
"title": "SOC 2 evidence — Q1 2026"
}'
The request is accepted, not performed: the response is 202 Accepted carrying the queued report.
{
"id": "0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c",
"tenant_id": "b2c3d4e5-6f70-4812-9a3b-4c5d6e7f8091",
"environment_id": "6f9f1f6c-1f5e-4a5b-9a1d-2f3c4d5e6f70",
"report_type": "soc2",
"title": "SOC 2 evidence — Q1 2026",
"status": "queued",
"error": null,
"subject_agent_id": null,
"framework_slug": null,
"period_start": "2026-01-01T00:00:00Z",
"period_end": "2026-03-01T00:00:00Z",
"report_data": { "requested_by": "user", "attempts": 0 },
"report_hash": null,
"content_version": null,
"evidence_count": 0,
"page_count": null,
"file_size_bytes": null,
"storage_path": null,
"previous_report_id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
"schedule_id": null,
"generated_by": "9d8c7b6a-5f4e-4d3c-2b1a-0f9e8d7c6b5a",
"generated_at": "2026-03-01T10:00:00Z",
"completed_at": null
}
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
report_type | enum | Yes | soc2, gdpr, iso27001, executive, inventory, ai_assessment or framework |
environment_id | uuid | Yes | The environment the report is filed under. Must belong to your organization. A report currently covers every environment in the organization — see Scope below |
subject_agent_id | uuid | For ai_assessment | The agent the assessment is about. Must be one of your agents. Rejected on every other type |
framework_slug | string | For framework | The framework to report on, e.g. eu_ai_act or nist_ai_rmf. Must be one the compliance library carries (GET /api/v1/compliance/frameworks). Rejected on every other type |
period_start | datetime | No | RFC 3339. Defaults to 30 days before the request |
period_end | datetime | No | RFC 3339. Defaults to the time of the request |
title | string | No | A name for the report, 200 characters at most. Without one, the type names it |
Viewers cannot generate reports; every other role can. A user whose access scope is scoped generates only AI assessments of the agents granted to them: any other report type answers 403 Forbidden, and an assessment of any other agent answers 400. At most 20 of an organization's reports can be queued or running at once.
Report status
| Status | Meaning |
|---|---|
queued | Accepted, waiting to be produced |
running | Being produced now |
ready | report_data is complete and, where report storage is configured, the PDF is in place |
failed | Generation did not succeed. error says why in one sentence |
Poll the report until it leaves queued and running:
curl https://api.mitrity.com/api/v1/reports/0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c \
-H "Authorization: Bearer mk_your-api-key"
{
"id": "0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c",
"report_type": "soc2",
"title": "SOC 2 evidence — Q1 2026",
"status": "ready",
"error": null,
"subject_agent_id": null,
"framework_slug": null,
"period_start": "2026-01-01T00:00:00Z",
"period_end": "2026-03-01T00:00:00Z",
"report_data": { "report_type": "soc2", "sections": {}, "integrity": {} },
"report_hash": "0f4c5b1d9a6e2f8c3b7d4e1a5c9f0b2d6e3a8c7f1b5d9e4a2c6f0b3d8e7a1c5f",
"content_version": "reporting-2026-09",
"evidence_count": 128,
"page_count": 9,
"file_size_bytes": 184203,
"storage_path": "b2c3d4e5-6f70-4812-9a3b-4c5d6e7f8091/soc2/0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c.pdf",
"previous_report_id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
"schedule_id": null,
"generated_by": "9d8c7b6a-5f4e-4d3c-2b1a-0f9e8d7c6b5a",
"generated_at": "2026-03-01T10:00:00Z",
"completed_at": "2026-03-01T10:00:12Z"
}
A report that was started and never finished — because the instance producing it stopped — is picked up again automatically. A report that repeatedly fails to finish ends as failed rather than retrying forever.
You do not have to poll. When a report becomes ready, the platform emits a report.ready notification: in the bell by default and to your webhook destinations, so a GRC or ticketing system learns that a report is on file without asking (notification events). Its payload names the report, its type, its period, its hash and how many records it cites. Slack and email for it are switched on in Settings → Notifications, like any other kind.
Report versions
Reports of the same type about the same subject form a chain. When a report is generated, previous_report_id is set to the last finished report of the same type — and, for an AI assessment or a framework report, about the same agent or framework — so a reader can follow the chain back and see what changed rather than guess which of two files is newer. The reports a schedule produces chain onto each other; reports generated by hand chain across the organization.
Regenerating a report never overwrites the earlier one. Each report is its own row with its own hash, and the dashboard links a report to the one it supersedes.
Downloading a report
The download endpoint returns a signed URL, not the file. The URL is valid for ten minutes.
curl https://api.mitrity.com/api/v1/reports/0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c/download \
-H "Authorization: Bearer mk_your-api-key"
{
"download_url": "https://storage.googleapis.com/...",
"expires_in": "600"
}
A report whose PDF has not been rendered answers 200 with a message instead; use report_data in that case, which holds every figure the PDF would have shown. Where report storage is not configured, the endpoint answers 503.
Exporting an evidence bundle
An auditor rarely wants only the PDF. The bundle endpoint packages a ready report as one zip: the report record, every record it cites, the PDF, the report hash and the signed audit checkpoint that covers the report's period. It is what you hand over when the reader has no account and should not need one.
curl https://api.mitrity.com/api/v1/reports/0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c/bundle \
-H "Authorization: Bearer mk_your-api-key"
{
"download_url": "https://storage.googleapis.com/...",
"expires_in": "600",
"exported_at": "2026-03-02T09:12:31Z",
"bundle": {
"version": "1.0",
"report_id": "0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c",
"report_type": "soc2",
"title": "SOC 2 evidence — Q1 2026",
"period_start": "2026-01-01T00:00:00Z",
"period_end": "2026-03-01T00:00:00Z",
"generated_at": "2026-03-01T10:00:00Z",
"completed_at": "2026-03-01T10:00:12Z",
"content_version": "reporting-2026-09",
"report_hash": "0f4c5b1d9a6e2f8c3b7d4e1a5c9f0b2d6e3a8c7f1b5d9e4a2c6f0b3d8e7a1c5f",
"evidence_count": 128,
"checkpoint": {
"id": "5c4d3e2f-1a0b-4c9d-8e7f-6a5b4c3d2e1f",
"period_start": "2026-02-28T02:00:00Z",
"period_end": "2026-03-01T02:00:00Z",
"first_seq": 180211,
"last_seq": 184970,
"event_count": 4760,
"root_hash": "8d1e6f2a...",
"prev_root_hash": "3b7c9d0e...",
"key_id": "3f9a1c2b7d8e4f60",
"signature": "...",
"signed_at": "2026-03-01T02:00:01Z",
"statement": "{\"v\":\"mitrity-audit-checkpoint/v1\",...}",
"statement_format": "mitrity-audit-checkpoint/v1",
"public_key": "...",
"public_key_url": "/api/v1/audit/checkpoints/public-key",
"verified": true
},
"files": [
{ "name": "report.json", "bytes": 18211, "sha256": "..." },
{ "name": "evidence.json", "bytes": 64873, "sha256": "..." },
{ "name": "report.pdf", "bytes": 184203, "sha256": "..." },
{ "name": "checkpoint.json", "bytes": 1188, "sha256": "..." },
{ "name": "hash.txt", "bytes": 73, "sha256": "..." }
],
"gaps": []
}
}
What the archive holds
| File | Contents |
|---|---|
manifest.json | This manifest: every other file with its size and SHA-256, the checkpoint proof and the gaps, so an archive that has been opened and re-zipped still says what it should contain |
report.json | The report's identity and figures: id, type, title, subject, period, content version, hash, evidence count, the report it supersedes, and report_data |
evidence.json | Every record the report cites, in section order: the section and control it supports, the kind of record, what it refers to, when it occurred, its one-sentence summary and its dashboard link. Capped at 10,000 records; the manifest says when the cap applied |
report.pdf | The rendered document, when one is on file |
checkpoint.json | The newest signed audit checkpoint whose period overlaps the report's — its statement, signature and key id — with the verifying key when the deployment has one, the route that serves it, and whether the platform verified the signature before writing the bundle |
hash.txt | The report hash, one line in sha256sum layout |
The manifest (bundle) is returned beside the URL and written into the archive as manifest.json. It lists each file with its size and SHA-256, the checkpoint proof, and gaps: what the bundle could not include, one sentence each — no rendered PDF, or one no longer on file; no checkpoint sealing the period; a report from before hashed reports; a truncated evidence list; fewer records on file than the report cites; a checkpoint whose signature did not verify against the deployment's key, or one the deployment could not check because it has no verifying key wired. An empty gaps means the bundle is complete. The same list is written to your audit trail with the export, as a report.bundle_exported event that also records the report hash, the files and who exported.
Delivery
As with the download endpoint, the answer is a signed URL valid for ten minutes, not the file. The archive is written once per report and covering checkpoint and never overwritten: a bundle an auditor already holds stays byte for byte what it was, and a checkpoint sealed later produces a new archive rather than replacing the old one. Asking again for the same report returns the existing archive with its manifest. Nothing in the archive depends on when it was built, so the same report and checkpoint always give the same bytes; exported_at on the response is when this export was recorded.
Only a ready report can be exported; a queued, running or failed report answers 400. Viewers can download a report but not export a bundle (403): an export writes to your storage and your audit trail, so it takes the roles that can generate a report. Where report storage is not configured, the endpoint answers 503.
Checking a bundle without an account
- Recompute the SHA-256 of each file and compare it with
manifest.json, or with the manifest the exporter received in the response. - Confirm that
hash.txtmatchesreport_hashinreport.jsonand the footer of every page ofreport.pdf. - Verify
checkpoint.json: the Ed25519signatureoverstatement, withpublic_key— or the key frompublic_key_url, which any signed-in user can fetch. That shows your audit trail was sealed over the period the report describes. Checking the cited audit events against the chain itself is verifying a period, a call your compliance team makes with an account.
Sharing a report
A share link opens a finished report for somebody who has no MITRITY account — an auditor, an insurer, a customer's security team. The link is the authorization, so it is built to be given away and taken back:
- The token is shown once. The response that creates the share is the only place the token and the
share_urlbuilt from it ever appear. MITRITY stores a fingerprint of the token and an 8-character prefix, so a copy of the database opens nothing, and a link that was not copied is replaced by creating a new one — never recovered. - Every link expires, never more than 90 days out.
- A link can cap its views (1–10,000). A capped link that has been opened that many times stops opening.
- A link can be revoked. A revoked link is indistinguishable from one that never existed.
- There is no password. A password sent beside the link protects nothing; the expiry, the view cap and the revoke are the controls.
Managers and owners can share a report, and only a ready report can be shared. A report can have at most 20 live links.
curl -X POST https://api.mitrity.com/api/v1/reports/0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c/shares \
-H "Authorization: Bearer mk_your-api-key" \
-H "Content-Type: application/json" \
-d '{
"label": "External auditor — Q1 engagement",
"expires_at": "2026-04-15T00:00:00Z",
"max_views": 5
}'
{
"id": "3c2b1a09-8f7e-4d6c-b5a4-3f2e1d0c9b8a",
"report_id": "0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c",
"token_prefix": "kQ7pL2mN",
"label": "External auditor — Q1 engagement",
"expires_at": "2026-04-15T00:00:00Z",
"max_views": 5,
"view_count": 0,
"last_viewed_at": null,
"created_by": "9d8c7b6a-5f4e-4d3c-2b1a-0f9e8d7c6b5a",
"created_at": "2026-03-01T11:00:00Z",
"revoked_at": null,
"revoked_by": null,
"revoked": false,
"expired": false,
"token": "kQ7pL2mN...",
"share_url": "https://mitrity.com/shared/reports#kQ7pL2mN..."
}
| Field | Type | Required | Description |
|---|---|---|---|
expires_at | datetime | Yes | RFC 3339, in the future, at most 90 days out |
max_views | integer | No | 1–10,000. Omit for no cap |
label | string | No | Who the link is for, 120 characters at most. Shown in the list, never to the reader |
GET /api/v1/reports/{id}/shares lists a report's links, newest first, by prefix — the token is never returned again. POST /api/v1/reports/{id}/shares/{share_id}/revoke revokes one; revoking a link that is already revoked answers 404.
What the reader sees
The link opens at /shared/reports#{token} without signing in. The token rides in the URL fragment, which never leaves the browser: it is not written to request logs and it is not sent in the referrer of any link on the page. The page shows what identifies the document — its type, title, period, when it was generated, its hash, when the link expires and, on a capped link, how many views remain — and a download link for the PDF, valid for ten minutes. It shows nothing that identifies your organization: no tenant, no agent identifiers, no author.
Behind the page is POST /api/v1/public/report-shares/redeem, which takes the token in the request body — {"token": "…"} — and answers the same facts as JSON. The token never travels in a URL, so it stays out of the request logs of every system between the reader and MITRITY. Opening a link counts one view and records an audit event (report.share_viewed) on your organization, so revoking a link is an informed decision. A link that is unknown, revoked, expired, past its view cap, or pointing at a report that has been deleted answers 404 with the same body in every case, and so does a request that carries no token, so the route cannot be used to learn which links exist. The route is rate-limited per client.
Scheduling reports
A schedule produces a report on a cadence. Each run covers the period since the last one and chains onto the report before it, so a monthly schedule builds a month-by-month record without anyone remembering to generate it.
Managers and owners can create, change and delete schedules; an organization can have at most 50. A manager whose access scope is scoped schedules only AI assessments of the agents granted to them.
curl -X POST https://api.mitrity.com/api/v1/reports/schedules \
-H "Authorization: Bearer mk_your-api-key" \
-H "Content-Type: application/json" \
-d '{
"report_type": "executive",
"environment_id": "6f9f1f6c-1f5e-4a5b-9a1d-2f3c4d5e6f70",
"title": "Monthly governance summary",
"cadence": "monthly",
"period_days": 30,
"hour_utc": 6
}'
| Field | Type | Required | Description |
|---|---|---|---|
report_type | enum | Yes | Any type you can generate. An ai_assessment schedule also needs subject_agent_id; a framework schedule also needs framework_slug |
environment_id | uuid | Yes | The environment the reports are filed under |
cadence | enum | Yes | weekly, monthly or quarterly |
period_days | integer | No | How many days each report covers, 1–366. Defaults to 30 |
hour_utc | integer | No | The hour of the day, 0–23 UTC, at which a run starts. Defaults to 6 |
title | string | No | A name for the reports the schedule produces |
enabled | boolean | No | Defaults to true |
The first run is the next occurrence of hour_utc — today if that hour is still ahead, tomorrow otherwise — so a schedule produces something the day it is created. The response carries next_run_at and, once it has run, last_run_at.
PUT /api/v1/reports/schedules/{schedule_id} changes the cadence, period, hour, title and enabled flag. The type and subject are fixed after creation: a schedule that changed subject would leave a chain whose earlier reports are about something else. next_run_at moves only when the cadence or the hour changes, or when a disabled schedule is re-enabled — renaming a schedule does not delay its next report.
DELETE /api/v1/reports/schedules/{schedule_id} stops the schedule. The reports it already produced stay: a schedule is the instruction, not the evidence.
Listing reports
curl "https://api.mitrity.com/api/v1/reports?report_type=soc2&limit=10" \
-H "Authorization: Bearer mk_your-api-key"
The response is an array of reports, newest first:
[
{
"id": "0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c",
"report_type": "soc2",
"title": "SOC 2 evidence — Q1 2026",
"status": "ready",
"report_hash": "0f4c5b1d9a6e2f8c3b7d4e1a5c9f0b2d6e3a8c7f1b5d9e4a2c6f0b3d8e7a1c5f",
"evidence_count": 128,
"page_count": 9,
"previous_report_id": "7a6b5c4d-3e2f-4a1b-8c9d-0e1f2a3b4c5d",
"generated_at": "2026-03-01T10:00:00Z",
"completed_at": "2026-03-01T10:00:12Z"
}
]
| Parameter | Type | Description |
|---|---|---|
report_type | enum | Restrict the list to one type. An unrecognized value is rejected rather than ignored |
limit | integer | Rows per page, 1–100. Default 50 |
offset | integer | Zero-based row offset. Default 0 |
The list holds the reports you can see. A user whose access scope is scoped sees only the AI assessments of the agents granted to them; organization reports are for Owners and users whose access scope is all. A report you cannot see answers 404 Not Found, whether you read, download, export, share or delete it.
Deleting a report
curl -X DELETE https://api.mitrity.com/api/v1/reports/0b1c9a7e-8f2d-4a31-9c77-1d2e3f4a5b6c \
-H "Authorization: Bearer mk_your-api-key"
Deleting removes the report from the list and from the API, and answers 204. Compliance evidence is not erased on request: the report and the records behind it are retained, they simply stop being served, and any share link on it stops opening. Managers and owners can delete a report; members and viewers cannot.
When an environment is deleted
Deleting an environment keeps the reports filed under it. Each becomes an organization report: its environment_id is null, and its evidence, file and share links stay as they were. What a report says does not change, since its figures already cover every environment, and neither does who can read it: organization reports are for Owners and users whose access scope is all, and an AI assessment follows its agent. The environment's report schedules are deleted with it; the reports they produced are kept the same way.
Evidence
Every figure in a report is backed by a record, and every record is kept with the report: what kind of record it is, where it came from, one sentence describing it, and a link into the dashboard — an audit event, an approval, a review, an agent, a policy.
Two rules govern what an evidence summary may say:
- It is written to be read without access to the underlying record. "A blocked attempt to reach a destination outside the agent's declared scope" is a summary; a row identifier is not.
- It never reproduces what a control was protecting. A data-loss summary names the pattern that matched and says how many values were found. It never shows a value. An AI assessment describes a runtime's sandbox by what it configures, never by the paths inside it.
An evidence link may point at a record that is no longer there — audit and runtime events are pruned on their own retention. The summary stays with the report either way, which is why it is written into the report rather than looked up when the report is read.
Data integrity
Every report ends with a data-integrity section:
- Report hash — a SHA-256 over the report's figures and over what the report says about each record it cites, taken in a canonical form. Two reports built from the same evidence carry the same hash; a changed figure, a changed citation or a different set of records produces a different one. The hash is printed in the footer of every page, so a page that leaves the document still says which report it came from. It shows that two documents describe the same evidence — it is not a signature, and it does not by itself prove who produced the document.
- Content version — which version of the report collectors produced it, so two reports over the same period can be compared meaningfully.
- Records cited and agents in scope — the size of the evidence the report rests on.
- Scope — which environments the figures cover.
- Governance records — how many changes people made through MITRITY in the period, for the organization or, in an AI assessment, about the agent. Examples are reviews, lifecycle changes and policy edits. They are on the same audit trail as the actions and are not counted among them. Other records states anything else on the trail that is not an agent's action, such as a connector reading its credentials, when there is any. With the actions, these account for every record in the period.
- Audit trail checkpoint — the latest signed checkpoint over your audit trail, for every report type: when it was sealed, the chain positions it covers, its root hash and a prefix of its signature. It also says whether the checkpoint covers the report's period, or whether events recorded after it are chained but not yet checkpointed.
- What the report could not see — for an organization report, agents with no runtime attestation, agents with no execution-coverage record, and connections whose last sync inside the period failed, each stated as a count. For an AI assessment, every statement the sections made about what was not on file — no attestation, no assessment, an empty risk register — repeated in one table. A report with no gaps says that too.
The hash covers the report and its evidence, not the integrity section that prints the hash. The governance-record and other-record counts are covered: they are stored with the report's figures, and the integrity section restates them.
Names in other scripts
Reports are rendered with fonts that cover Latin text. An agent, owner or policy named in Japanese, Chinese or Korean is set in an embedded typeface that carries those scripts, so a name renders as the name rather than as substituted characters.
Best practices
Generate before the audit, not during
Generate a report a week before an audit. The gaps it states are the ones you still have time to close.
Read the gaps first
The integrity section is the first thing an auditor will ask about. An agent with no runtime attestation can act outside the decisions the report shows — know which agents those are before someone else finds them.
Read the scope line
A report is filed under one environment but its figures cover every environment in your organization; the integrity section says so on the document. If you need production evidence on its own, say so in the report's title and read the scope line before handing it to an auditor — per-environment collection is not there yet.
Share a link, not a file
A PDF forwarded by email cannot be taken back. A share link with an expiry that matches the engagement and a view cap that matches the reader can, and every open is recorded against your organization.
Keep your own copy
Download and archive the PDF in your own document system, and keep the report hash with it: comparing the hash against a regenerated report tells you whether the two describe the same evidence. The evidence bundle keeps the PDF, the hash and the records the report cites together with the checkpoint that seals the period, in one archive.
Pair an assessment or a framework report with the inventory
The inventory report gives an auditor the context — which agents exist, under which policies — that an AI assessment of one agent or a framework report assumes.
Related documentation
- ML Insights — drift scoring and behavioral analytics
- RBAC — who can generate, share, schedule and delete reports
- Environments — the environment a report is filed under
- Tamper-Evident Audit Trail — the checkpoints an evidence bundle carries, and how to verify a period
- SIEM Integration — the
report.readynotification and its envelope - API Overview — authentication and conventions