Aira

DORA API

Endpoints for the Digital Operational Resilience Act (EU 2022/2554) — incidents, ICT third-party register, and resilience tests.

Endpoints

MethodPathDescription
POST/dora/incidentsOpen a new ICT incident (Article 17)
GET/dora/incidentsList incidents with filters
GET/dora/incidents/{uuid}Get one incident
PUT/dora/incidents/{uuid}/classifyClassify severity/category (Article 18)
PUT/dora/incidents/{uuid}/resolveMark resolved + record lessons learned
GET/dora/incidents/{uuid}/reportDownload signed major-incident PDF (Article 19)
POST/dora/third-partiesRegister an ICT third party (Article 28)
GET/dora/third-partiesList registered third parties
GET/dora/third-parties/{uuid}Get one third party
PUT/dora/third-parties/{uuid}Update third-party fields (PATCH semantics)
POST/dora/testsLog a resilience test (Articles 24–27)
GET/dora/testsList resilience tests

All endpoints require a Bearer API key. The route group is gated by the ENABLE_DORA setting; when disabled all endpoints return 404.

Create an incident

POST /api/v1/dora/incidents

Request body

FieldTypeRequiredDescription
titlestringyesHuman-readable title
descriptionstringyesWhat happened
detected_atdatetimeyesISO 8601 UTC
affected_servicesstring[]noList of internal service identifiers
clients_affected_countintnoDefaults to 0
geographic_scopestring[]noList of country/region codes
related_action_uuidsstring[]noAira action UUIDs involved in the incident

Response

{
  "uuid": "i-...",
  "title": "Payments API outage",
  "status": "detected",
  "severity": null,
  "category": null,
  "is_major": false,
  "detected_at": "2026-04-15T10:00:00Z",
  "classified_at": null,
  "resolved_at": null,
  "reported_at": null,
  "clients_affected_count": 1500,
  "has_report": false,
  "created_at": "2026-04-15T10:00:00Z",
  "org_uuid": "...",
  "description": "...",
  "affected_services": ["payments-api"],
  "request_id": "req_..."
}

Classify an incident

PUT /api/v1/dora/incidents/{uuid}/classify
FieldTypeRequiredDescription
severitystringyescritical / high / medium / low
categorystringyesSee DORA incident reporting
is_majorboolnoOverride auto-promotion (critical/high → major)
root_cause_summarystringnoFree-text narrative
root_cause_classificationstringnoSee root cause vocab
third_party_uuidstringyes when category = third_party_failureLink into the ICT third-party register

Errors

CodeWhen
400 INVALID_STATEIncident is not in detected state
400 THIRD_PARTY_REQUIREDCategory is third_party_failure but no third_party_uuid
404 NOT_FOUNDIncident does not belong to the caller's org

Resolve an incident

PUT /api/v1/dora/incidents/{uuid}/resolve
FieldTypeRequired
resolution_summarystringyes
lessons_learnedstringno
resolved_atdatetimeno — defaults to server time

Only allowed when the incident is in classified state.

Download the signed report

GET /api/v1/dora/incidents/{uuid}/report

Returns application/pdf. Only valid for incidents where is_major = true and status != "detected". First call generates and signs the PDF; subsequent calls serve the cached bytes.

Evidence fields (exposed on the incident detail)

FieldMeaning
report_content_hashSHA-256 of the canonical PDF bytes
report_signatureEd25519 signature over the hash
report_signing_key_idJWKS key ID — verifiable at /.well-known/jwks.json
report_signed_atWhen the signature was produced

Third-party register

POST /api/v1/dora/third-parties
FieldTypeRequired
vendor_namestringyes
service_descriptionstringyes
service_typestringyes — see the type list
criticalitystringyes — critical / non_critical / supporting
contract_start_datedateno
contract_end_datedateno
exit_strategy_summarystringrequired when criticality = critical
subcontractorsstring[]no
data_categoriesstring[]no
jurisdictionstringno

PUT /api/v1/dora/third-parties/{uuid} uses PATCH semantics — only fields present in the body change, others stay as-is. is_active=false soft-retires without deleting.

Resilience tests

POST /api/v1/dora/tests
FieldTypeRequired
test_typestringyes — tlpt, vulnerability_scan, scenario_based, performance, resilience_drill, other
titlestringyes
scopestringyes — what was tested
conducted_atdateyes
conducted_bystringyes — internal team or external tester name
statusstringyes — passed / failed / partial
findings_summarystringno
remediation_planstringno
remediation_due_atdateno

TLPT results are append-only — there is no PUT for the test record (findings and remediation must be tracked in a follow-up test, not by rewriting history).

On this page