Reports API
Report reads require ro:reports; changes require rw:reports. Both are limited to the reports visible to the key's owner. A known report ID can return 404 when team restrictions hide it.
Use X-API-Key for authentication. The examples below assume VULNOTES_URL contains your instance URL without a trailing slash and VULNOTES_API_KEY contains your key.
Create a report
curl --fail-with-body "$VULNOTES_URL/api/reports" \
-H "X-API-Key: $VULNOTES_API_KEY" \
-H "Content-Type: application/json" \
--data '{"title":"External assessment","language":"EN"}'The response contains the report's _id. To link existing resources at creation, include company, template, and vulnTemplate or vulnTemplates using their IDs.
Common operations
All paths below are relative to /api.
| Method and path | Use |
|---|---|
GET /reports?page=1&limit=25 | List accessible reports |
GET /reports/{id} | Read a report |
PUT /reports/{id} | Update supplied report fields |
POST /reports/{id}/duplicate | Create an independent draft copy |
GET /reports/{id}/findings | List findings |
POST /reports/{id}/findings | Add a finding |
POST /reports/{id}/findings/from-library | Add a library item using vulnerabilityId |
PUT /reports/{id}/findings/{findingId} | Update a finding |
PUT /reports/{id}/content/{sectionKey} | Update one content section |
Findings use an id string inside the report; it is different from the report's MongoDB _id. Read the linked vulnerability templates before sending dynamic field data.
Read the report's content map and linked template to identify section keys. Send content and/or isComplete to PUT /reports/{id}/content/{sectionKey}, or use client.reports.update_content_section() in the Python SDK. Sending a complete content map to PUT /reports/{id} is rejected; update each section separately.
Status and copies
Valid report statuses are draft, waiting-for-review, under-review, and completed. Completing a report can create its final PDF archive and schedule retention deletion. Treat it as a workflow transition.
Duplication creates a new draft with separate editable content and copied owned files. The copy stays in the source report's group but starts without its review, client remediation, or retest state.
Export
| Method and path | Result |
|---|---|
GET /reports/{id}/export/json | Report backup as JSON |
GET /reports/{id}/export/pdf | Generated PDF |
POST /reports/{id}/export/docx | Word document |
POST /reports/{id}/export/xlsx | Finding spreadsheet |
POST /reports/{id}/export/zip | Export archive |
GET /reports/{id}/archive | Stored completion PDF, when available |
Export requests require ro:reports. Check the reference for format-specific request options. Save binary responses to a file; use --fail-with-body so an error response is not mistaken for a valid export.
A report JSON backup is different from the library/client ZIP exported in Settings > Integrations.
