Compliance Reports API
One API produces a formatted, regulator-appropriate artifact from the governance data AxonFlow already holds. You choose a regulator, a framework and a reporting period; AxonFlow renders a real PDF, CSV, XLSX or JSON file, stores it, and hands you a time-limited download link.
Before this API, every "export" on the platform was raw JSON. This one produces the document you attach to a submission.
:::tip Looking for the Customer Portal walkthrough? This page is the API reference. If you want to select a jurisdiction, read your live posture, and generate a report from the Customer Portal UI, see Compliance Reports (Customer Portal). :::
:::info Enterprise feature Report generation requires an Evaluation or Enterprise licence. On the Community edition the routes are not registered. See Community vs Enterprise. :::
Quickstart
Three calls: create, poll, download.
# 1. Create. Returns 202 immediately with a job id.
curl -sS -X POST "$AXONFLOW_URL/api/v1/compliance/reports" \
-H "Content-Type: application/json" \
-d '{
"regulator": "euaiact",
"framework": "EU_AI_ACT",
"format": "pdf",
"period_start": "2026-04-01T00:00:00Z",
"period_end": "2026-06-30T23:59:59Z"
}'
# {"id":"creport-9f3c...","status":"pending","report_state":"","progress":0, ...}
# 2. Poll until status is `completed` or `failed`.
curl -sS "$AXONFLOW_URL/api/v1/compliance/reports/creport-9f3c..."
# {"id":"creport-9f3c...","status":"completed","report_state":"populated",
# "progress":100,"record_count":184,"checksum":"3b1f...","size_bytes":58213, ...}
# 3. Download. Responds 307 to a presigned URL valid for one hour.
curl -sSL -o eu-ai-act-q2.pdf \
"$AXONFLOW_URL/api/v1/compliance/reports/creport-9f3c.../download"
Requests are scoped by the X-Org-ID and X-Tenant-ID headers, which the
AxonFlow Agent gateway and the customer portal proxy set from your validated
credential. You never send them by hand from an application.
The three endpoints
| Method | Path | Success | Purpose |
|---|---|---|---|
POST | /api/v1/compliance/reports | 202 Accepted | Create a report job |
GET | /api/v1/compliance/reports/{id} | 200 OK | Poll job status |
GET | /api/v1/compliance/reports/{id}/download | 307 Temporary Redirect | Presigned artifact URL (1 hour) |
Generation is asynchronous because a multi-year OJK report over a busy tenant is not a request-timeout-sized amount of work. The create call returns as soon as the job is durably recorded.
Statuses
status | Meaning |
|---|---|
pending | Recorded, not started |
processing | Collecting data and rendering |
completed | Artifact stored and checksummed - downloadable |
failed | Terminal failure; error names the cause |
A job reaches completed only when a checksummed artifact is durably
stored. If no artifact storage backend is configured, the job fails with an
error naming the missing configuration rather than reporting success you cannot
download.
report_state: the three-state answer
Every create and poll response carries an explicit report_state. It exists
because an empty report is ambiguous, and the two readings need different
responses from you:
report_state | Meaning | What to do |
|---|---|---|
not_available | The regulator's module is not enabled in this deployment | Enable the module, or pick a different regulator |
enabled_empty | The module is enabled and the period genuinely contains no governed activity | Nothing - this is a valid "no activity in range" attestation |
populated | The module is enabled and returned data | Nothing |
| (empty string) | Not determined yet | The job is still pending or processing. Poll again. |
The field is always present on every create and poll response, including while it is the empty string. You never have to tell "absent" from "null" to work out what happened.
not_available is also returned synchronously: creating a report for a
regulator whose module is not enabled is refused with 409 Conflict and
{"error_code":"REGULATOR_NOT_AVAILABLE","report_state":"not_available"}
rather than producing a job that can never succeed.
Regulators, frameworks and formats
| Regulator | regulator | framework | Formats | Retention shown on the artifact |
|---|---|---|---|---|
| EU AI Act | euaiact | EU_AI_ACT | pdf, csv, json | Logs at least 6 months (Art. 12/19); technical documentation 10 years (Art. 18) |
| SEBI (India) | sebi | SEBI_AI_ML | pdf, csv, xlsx, json | 5 years |
| RBI FREE-AI (India) | rbi | RBI_FREE_AI | pdf, csv, xlsx, json | Per the FREE-AI framework and the board-approved policy |
| MAS FEAT (Singapore) | masfeat | MAS_FEAT | pdf, csv, json | 7 years |
| OJK / BI / UU PDP (Indonesia) | ojk | OJK_AI_GOVERNANCE, UU_PDP, BI_PJP, OJK_BI_COMBINED | pdf, csv, json | 5 years |
framework may be omitted for the four regulators that define exactly one. It
is required for ojk, which reports against three different Indonesian
instruments - selecting one for you would file the report under the wrong law.
XLSX is offered only where the regulator's own submission practice is
spreadsheet-shaped. Requesting a format a regulator does not offer is a
400 with UNSUPPORTED_FORMAT and the supported list in the message.
What each report contains
| Regulator | Sections |
|---|---|
| EU AI Act | Conformity assessments (Art. 43), Article 43 summary, risk management (Arts. 9-17), accuracy and bias monitoring (Art. 15), human oversight (Art. 14), audit trail (Art. 12) |
| SEBI | Readiness checks, policy violations, LLM activity, decision-chain lineage, human oversight, PII redactions, retention posture |
| RBI FREE-AI | Board reports, AI incidents, kill switches, kill-switch activation history, model validations, AI system registry |
| MAS FEAT | FEAT assessments, four-pillar summary, AI system registry, kill-switch history |
| OJK / BI / UU PDP | AI governance summary, policy violations, LLM and decision activity, human oversight, PII redactions, cross-border transfers (UU PDP Pasal 56), 72-hour breach log (Art. 46), BI PJP, retention posture |
Sections are always emitted, even when empty, carrying a sentence saying so. A dropped section would make "we recorded no HITL oversight" indistinguishable from "this report does not cover HITL oversight", which on a regulatory artifact is a different claim.
Access control
Two different authorities, deliberately:
| Action | Required |
|---|---|
| Poll report status | audit:read - any caller who may read the audit trail |
| Create a report | Administrator (owner, admin or policy admin) |
| Download an artifact | Administrator |
Generating and downloading produce a whole-tenant compliance artifact, so they
sit in the same authority class as
evidence export. Polling returns job metadata
only - id, status, progress, report_state, checksum - and no audit content, so
a compliance viewer can watch a report they requested reach completion.
Every by-id path is scoped to the caller's own organization and tenant. A
report id belonging to another tenancy returns 404, byte-identical to an
unknown id, so the endpoint cannot be used to discover which report ids exist.
Errors
| HTTP | error_code | Cause |
|---|---|---|
400 | UNKNOWN_REGULATOR | regulator is not one of the five |
400 | UNKNOWN_FRAMEWORK | Framework missing for ojk, or not defined for the regulator |
400 | UNSUPPORTED_FORMAT | Format unknown, or not offered for that regulator |
400 | INVALID_PERIOD | Missing, inverted, zero-length, or longer than 1096 days |
400 | INVALID_BODY | Malformed JSON, or an unrecognised field |
401 | SCOPE_REQUIRED | No X-Org-ID / X-Tenant-ID - the request did not traverse an authenticating hop |
403 | COMPLIANCE_REPORT_REQUIRES_EVALUATION_LICENSE | Community tier |
404 | REPORT_NOT_FOUND | No such report in your tenancy |
409 | REGULATOR_NOT_AVAILABLE | That regulator's module is not enabled here |
409 | REPORT_NOT_COMPLETED | Download requested before the job finished; the message carries the failure cause when it failed |
409 | REPORT_ARTIFACT_UNAVAILABLE | The job completed but its stored artifact is no longer retrievable |
429 | COMPLIANCE_REPORT_LIMIT_EXCEEDED | Daily report budget for your tier |
503 | INTERNAL_ERROR | The service has no database connection |
Reports share the daily budget of the evidence-export tier: 3 per day on Evaluation, unlimited on Enterprise. A refused request - a malformed body, a tier refusal, an unavailable regulator - does not consume a slot.
Artifacts
Artifacts are stored in the object-storage backend the orchestrator is
configured with (AUDIT_EXPORT_STORAGE_TYPE and its bucket/credential
variables) under compliance-reports/{org}/{regulator}/{report-id}.{ext}. The
download endpoint mints a presigned URL valid for one hour; the orchestrator
never streams the bytes itself.
Each job records the SHA-256 of the artifact. Rendering is deterministic: the same job rendered twice produces byte-identical output, including the PDF's creation date, which is taken from the job record rather than the render clock. That is what makes the stored checksum a durable integrity claim rather than a one-time snapshot.
Known limitations
- PDF glyph coverage. PDFs use the standard 14 core fonts so nothing is
embedded and an air-gapped build produces the same bytes as any other. Those
fonts are cp1252-encoded, so a character outside that set - Devanagari, Han,
an emoji - renders as
?. Requestjsonorcsvwhen the data contains them; both carry full Unicode. - Row cap. Any single section is capped at 5,000 rows. When a section is truncated it says so, with the number of rows not shown. Narrow the reporting period for the full set.
- BI PJP. Selecting
BI_PJPorOJK_BI_COMBINEDscopes the export, but the Bank Indonesia framework contributes no payment-service-specific data class of its own yet. The report says so in that section rather than showing it empty. - Legacy per-module exports. The older per-regulator export endpoints remain
available and unchanged, with two corrections: SEBI's CSV export now returns
real CSV, and its XML format returns
501 Not Implementedinstead of JSON under an XML content type. RBI's PDF and XLSX exports are now real PDF and real XLSX. New integrations should use this API.
Related
- Compliance Reports (Customer Portal) - the same capability from the portal UI, for a compliance officer who is not calling the API directly
- Evidence export - the audit-bundle export this API shares an authority class and daily budget with
- Enterprise Compliance API Surface - the per-regulator endpoints this facade sits in front of
