8.4 KiB
Ivanti / RiskSense API Reference
Base URL: https://platform4.risksense.com/api/v1
Swagger: https://platform4.risksense.com/doc/swagger.json
Auth: x-api-key header. Error codes: 401 bad key, 419 insufficient privileges, 429 rate limited.
Endpoints Used
Search Workflow Batches
POST /client/{clientId}/workflowBatch/search
Content-Type: application/json
Standard JSON body with filters, projection, sort, page, size. Used by ivantiWorkflows.js for the daily sync.
Create False Positive Workflow
POST /client/{clientId}/workflowBatch/falsePositive/request
Content-Type: multipart/form-data
This endpoint does NOT accept JSON. It requires multipart/form-data with the following fields:
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string | yes | Workflow batch name (max 255) |
reason |
string | yes | Reason for the FP determination |
description |
string | yes | Description (can be empty string but field must be present) |
expirationDate |
string | yes | ISO-8601 date, e.g. 2026-06-01 |
overrideControl |
string | yes | AUTHORIZED, NONE, or AUTOMATED. Use AUTHORIZED for standard FP workflows. NONE with isEmptyWorkflow=true is rejected (400). |
isEmptyWorkflow |
boolean | yes | true if no findings attached, false otherwise |
subjectFilterRequest |
string | yes | Stringified JSON (see format below) |
files |
file | no | Attachments sent inline in the same request |
subjectFilterRequest format
This is the critical field. It must be a stringified JSON object with this exact structure:
{
"subject": "hostFinding",
"filterRequest": {
"filters": [
{
"field": "id",
"exclusive": false,
"operator": "IN",
"value": "2283734550,2283734551"
}
]
}
}
Key details:
subjectmust be"hostFinding"— without this, the API returns 500filtersis nested insidefilterRequest, NOT at the top level —{"filters":[]}at the top level returns 500valuefor multiple IDs is comma-separated as a single string, not an arrayoperatorvalues:EXACT,IN,LIKE,WILDCARD,RANGE,CIDR- For empty workflows, use
{"subject":"hostFinding","filterRequest":{"filters":[]}}withisEmptyWorkflow=true
Response (200/202)
{
"id": 33418832,
"created": "2026-04-08T18:16:08"
}
Returns HTTP 200 or 202 (Accepted — async job creation). Response contains a numeric id (the workflow batch job ID) and created timestamp. No generatedId or uuid in this response.
Map Findings to Existing Workflow (tested 2026-04-13)
POST /client/{clientId}/workflowBatch/falsePositive/{workflowBatchUuid}/map
Content-Type: application/json
Maps additional host findings to an existing FP workflow batch. Used by the FP submission editing feature to add findings after initial creation.
Critical: one finding per call. The map endpoint only reliably maps one finding per request. Sending multiple finding IDs via the IN operator or comma-separated values results in only the first finding being mapped. The multipart/form-data format (used by the create endpoint) returns 500 on this endpoint.
Request body
{
"subject": "hostFinding",
"filterRequest": {
"filters": [
{
"field": "id",
"exclusive": false,
"operator": "EXACT",
"value": "2283734550"
}
]
}
}
Key details:
- Must be
application/json(NOT multipart/form-data — returns 500) - Use
EXACToperator with a single finding ID per call INoperator with comma-separated IDs only maps the first finding- Loop through findings and make one API call per finding
- The
workflowBatchUuidin the URL is the UUID from the search endpoint (not the numeric batch ID from create)
Response (200)
Returns the updated workflow batch object on success.
UUID resolution
The workflowBatchUuid required in the URL is NOT returned by the create endpoint. To obtain it:
- Search via
POST /client/{clientId}/workflowBatch/searchwith{ field: 'name', operator: 'EXACT', value: '<workflow_name>' } - Use
projection: 'internal'to get full batch objects - The UUID is in the
uuidfield of the returned batch object - Cache the UUID locally after first resolution (stored in
ivanti_fp_submissions.ivanti_workflow_batch_uuid)
Implementation in dashboard
The resolveWorkflowBatchUuid() helper in backend/routes/ivantiFpWorkflow.js handles UUID resolution:
- Returns cached UUID if available in the local submission record
- Otherwise searches Ivanti by workflow name, extracts
batch.uuid, and caches it for future use
The findings map loop in the POST /submissions/:id/findings endpoint:
- Iterates through each finding ID individually
- Makes one JSON POST per finding with
EXACToperator - Tracks which findings succeeded vs failed
- Only marks queue items as complete for successfully mapped findings
- Returns both
addedFindingsandfailedFindingsarrays in the response
Other Workflow Endpoints (from Swagger)
These are available but not all are currently used by the dashboard:
| Endpoint | Purpose | Status |
|---|---|---|
/workflowBatch/acceptance/request |
Risk acceptance workflow | Not used |
/workflowBatch/remediation/request |
Remediation workflow | Not used |
/workflowBatch/severityChange/request |
Severity change workflow | Not used |
/workflowBatch/{workflowType}/approve |
Approve a workflow (needs workflowBatchUuid) |
Not used |
/workflowBatch/{workflowType}/reject |
Reject a workflow | Not used |
/workflowBatch/{workflowType}/rework |
Send back for rework | Not used |
/workflowBatch/{workflowType}/update |
Update a workflow | Not used |
/workflowBatch/{workflowType}/{workflowBatchUuid}/map |
Map findings to workflow | Used (FP editing) |
/workflowBatch/{workflowType}/{workflowBatchUuid}/unmap |
Unmap findings | Not used |
/workflowBatch/{workflowType}/{workflowBatchUuid}/attach |
Attach file to existing workflow | Broken — see note |
/workflowBatch/{workflowType}/{workflowBatchUuid}/detach |
Detach file | Not used |
/workflowBatch/model |
Get model/schema | Not used |
/workflowBatch/filter |
Get available filter fields | Not used |
/workflowBatch/suggest |
Get suggested values for a filter field | Not used |
Known Limitations
Attach endpoint does not work (tested 2026-04-13)
The /workflowBatch/{workflowType}/{workflowBatchUuid}/attach endpoint is listed in the Swagger spec but returns HTTP 400 (Bad Request) for all tested request formats:
multipart/form-datawith field namefile(singular) — 400multipart/form-datawith field namefiles(plural) — 400- Tested with
Content-Type: application/octet-streamandimage/png— both 400 - Tested with both
ivantiMultipartPostandivantiFormPosthelpers — both 400
The Ivanti response is a generic Spring Boot error with no detail message:
{"timestamp":"...","status":400,"error":"Bad Request","path":"/api/v1/client/1550/workflowBatch/falsePositive/{uuid}/attach"}
Workaround: File attachments can only be uploaded during the initial workflow creation (sent inline with the /workflowBatch/falsePositive/request endpoint). To add attachments to an existing workflow, users must upload them directly in the Ivanti platform UI.
Search by numeric batch ID does not work
The /workflowBatch/search endpoint does not support filtering by the numeric id returned from the create endpoint. Searching with { field: 'id', operator: 'EXACT', value: '33432541' } returns 0 results. Searching by name field works and returns the workflow batch object including the uuid field needed for map/attach operations.
UUID not returned by create endpoint
The /workflowBatch/falsePositive/request create endpoint returns only { id: <number>, created: <timestamp> }. The uuid needed for map/attach/approve/reject operations must be obtained separately via the search endpoint.
Environment Variables
| Variable | Default | Description |
|---|---|---|
IVANTI_API_KEY |
— | Required. API key for authentication |
IVANTI_CLIENT_ID |
1550 |
Client ID in the Ivanti platform |
IVANTI_SKIP_TLS |
false |
Set true to skip TLS verification |
IVANTI_FIRST_NAME |
— | Used for workflow search filter (sync) |
IVANTI_LAST_NAME |
— | Used for workflow search filter (sync) |