REST API
Authenticate with a personal API key, understand what the key can do, and find the interactive OpenAPI reference inside your workspace.
The REST API lives at /rest/v1 on your workspace origin, for example https://acme.vulnsy.com/rest/v1
(or your own hostname on a self-hosted install). It covers clients, projects, reports and their tabs,
findings, the finding and style libraries, evidence images, users, scanner and Markdown import, and
DOCX, CSV and Markdown export.
Interactive reference
The full, always-current reference is inside your workspace at /api-docs (Swagger UI). It is generated
from the same OpenAPI document the API is built against, served at /api/rest-docs/openapi, so you can also
load it into Postman, Insomnia or a code generator.
Create an API key
- Open Profile in your workspace and go to the API keys tab.
- Give the key a name, choose its scope and an expiry (one year by default).
- Copy the key when it is shown. It starts with
vulnsy_sk_and is shown once.
Send it as a bearer token:
curl -H "Authorization: Bearer vulnsy_sk_..." \
"https://acme.vulnsy.com/rest/v1/reports?per_page=10"Keys are personal. An administrator can see and revoke every key in the organization, and deactivating a user revokes theirs.
What a key can do
A request is allowed only when every one of these agrees:
- Plan or licence. Business plan and above on vulnsy.com; a self-hosted licence with the API feature.
- Key scope. A read-only key cannot create, change or delete anything.
- Your role. The key inherits your role's permissions, exactly as in the web app.
- Grants. External collaborators (third-party users) only see the reports and projects shared with them.
- Client allow-list. Edits, deletes and evidence uploads also require the affected client to be on the allow-list in your profile's API keys tab. Reads, exports and plain creates are not restricted by it.
Anything you are not allowed to see answers 404, so ids cannot be probed.
Conventions
- Pagination. List endpoints take
pageandper_page(max 100) and return the rows as a JSON array withX-Total-Count,X-Page,X-Per-PageandX-Total-Pagesheaders. - Filtering. Each list documents its filters in
/api-docs; most takeqfor text search andidto fetch one row. Unknown query parameters are ignored. - Idempotency. The creating endpoints (
POST /findings,/report-findings,/reports/import-markdown,/reports/{id}/import-scan) honour anIdempotency-Keyheader for 24 hours: a retry with the same key and body returns the original response withIdempotent-Replayed: true. - Optimistic concurrency.
PATCHon findings, reports and tabs acceptsexpectedUpdatedAt; if the row changed since you read it the API answers409 conflict. - Deletes. Clients, projects and reports go to the workspace trash and can be restored by an administrator. Findings, tabs, images and report links are deleted permanently.
- Errors are JSON:
{ "error": { "code": "...", "message": "..." } }.
Rate limits
| Limit | Value |
|---|---|
| Per IP address | 120 requests / minute |
| Per API key | 600 requests / minute |
| DOCX export, Markdown import | count as 10 requests each |
A limited request answers 429 with a Retry-After header.
Scanner and Markdown import
POST /rest/v1/reports/{id}/import-scan accepts a Nessus, Burp, Nmap or Nuclei file as multipart (up to
4 MB) or already-parsed findings as JSON (no size limit beyond the request cap), and behaves exactly like the
Import from scanner dialog in the report editor. POST /rest/v1/reports/import-markdown creates a whole
report from the Markdown that GET /rest/v1/reports/{id}/export-markdown produces, so export, edit and
import round-trip.