Onboarding Service Scanner Operations API - Consumer Guide Overview
来源:upwindsecurity.atlassian.net/wiki/spaces…
导出时间:2026-03-03
Overview
This guide provides practical examples for consuming the scanner operations endpoints. For complete API specifications, refer to the Swagger documentation available at:
http://onboarding-service.dev.internal:8082/swagger/index.html
Base URL: http://onboarding-service.dev.internal:8082/api/v1
Authentication
All endpoints require JWT bearer token authentication. Include your token in the Authorization header:
Authorization: Bearer <your-jwt-token>
The JWT token must contain an org-id claim that matches the {orgID} path parameter in the requests.
Understanding Operation Types
Asynchronous Operations (202 Accepted)
Operations that involve cloud infrastructure changes return 202 Accepted and execute in the background via Argo workflows:
- Remove Scanner
- Reinstall Scanner
- Batch Remove Scanners
- Batch Reinstall Scanners
- Remove Cloud Organisation
Async Response Structure:
{
"jobId": "rm-scan-cfg-scanner-123-1733980800",
"statusUrl": "/api/v1/jobs/rm-scan-cfg-scanner-123-1733980800",
"jobInfo": {}
}
Response Headers:
Location: /api/v1/jobs/{jobId}- URL to poll for statusRetry-After: 30- Recommended polling interval (seconds)
What to do next:
- Store the
jobIdfor tracking - Poll the
statusUrlto check operation status - Wait at least 30 seconds between poll requests
Synchronous Operations (200 OK)
Operations that only update internal state return 200 OK immediately:
- Disable Scanner (Pause)
- Enable Scanner (Unpause)
- Batch Pause Scanners
- Batch Unpause Scanners
These complete instantly and return final results in the response.
Remove Scanner
Asynchronously removes a scanner's cloud infrastructure and configuration.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/remove" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"configId": "'${CONFIG_ID}'",
"cloudProvider": "aws"
}'
Response (202 Accepted)
{
"jobId": "rm-scan-cfg-scanner-123-1733980800",
"statusUrl": "/api/v1/jobs/rm-scan-cfg-scanner-123-1733980800",
}
Poll Job Status
curl -X GET "${HOST}/api/v1/jobs/rm-scan-cfg-scanner-123-1733980800" \
-H "Authorization: Bearer ${TOKEN}"
Status Response:
{
"workflowName": "rm-scan-cfg-scanner-123-1733980800",
"status": "running",
"configId": "'${CONFIG_ID}'",
"orgId": "org_abc123",
"cloudProvider": "aws",
"region": "us-east-1",
"currentStep": "awaiting-stack-deleted",
"retryAttempt": 2,
"createdAt": "2025-01-12T10:00:00Z",
"updatedAt": "2025-01-12T10:05:30Z",
"error": null
}
Status Values:
pending- Workflow queuedrunning- Operation in progresssucceeded- Operation completed successfullyfailed- Operation failed (seeerrorfield)
Batch Remove Scanners
Asynchronously removes multiple scanners in parallel via Argo workflows.
Each scanner in the batch is processed independently (best-effort). If one scanner fails validation or submission, the others continue. A parent correlation ID groups all child workflows for aggregated status tracking.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/batch/remove" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"scanners": [
{ "configID": "cfg-scanner-001", "cloudProvider": "aws" },
{ "configID": "cfg-scanner-002", "cloudProvider": "aws" }
]
}'
Response (202 Accepted)
{
"jobId": "rm-scan-550e8400-e29b-41d4-a716-446655440000",
"statusUrl": "/api/v1/jobs?parent-id=rm-scan-550e8400-e29b-41d4-a716-446655440000",
"jobInfo": {
"results": [
{
"configID": "cfg-scanner-001",
"cloudProvider": "aws",
"success": true,
"status": "dispatched",
"workflowName": "rm-scan-cfg-scanner-001-1733980800"
},
{
"configID": "cfg-scanner-002",
"cloudProvider": "aws",
"success": true,
"status": "dispatched",
"workflowName": "rm-scan-cfg-scanner-002-1733980801"
}
]
}
}
Response Headers:
Location: /api/v1/jobs?parent-id={jobId}- URL to poll for aggregated statusRetry-After: 30- Recommended polling interval (seconds)
Per-scanner result fields:
success: true— workflow submitted successfully (not yet completed)success: false— submission failed; checkerrorfieldstatus—"dispatched"(workflow created) or"error"(failed to submit)workflowName— only present whensuccess: true
Poll Batch Status
curl -X GET "${HOST}/api/v1/jobs?parent-id=rm-scan-550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer ${TOKEN}"
Batch Status Response:
{
"parentID": "rm-scan-550e8400-e29b-41d4-a716-446655440000",
"summary": {
"total": 2,
"running": 1,
"completed": 1,
"failed": 0
},
"jobs": [
{
"workflowName": "rm-scan-cfg-scanner-001-1733980800",
"status": "completed",
"configId": "cfg-scanner-001",
"orgId": "org_abc123",
"cloudProvider": "aws",
"region": "us-east-1",
"currentStep": "completed",
"createdAt": "2025-01-12T10:00:00Z",
"updatedAt": "2025-01-12T10:03:00Z"
},
{
"workflowName": "rm-scan-cfg-scanner-002-1733980801",
"status": "running",
"configId": "cfg-scanner-002",
"orgId": "org_abc123",
"cloudProvider": "aws",
"region": "eu-west-1",
"currentStep": "awaiting-stack-deleted",
"createdAt": "2025-01-12T10:00:00Z",
"updatedAt": "2025-01-12T10:02:00Z"
}
]
}
Batch Reinstall Scanners
Asynchronously reinstalls multiple scanners via the management reinstall path.
Each scanner is delegated to the management reinstall handler (OnReInstallCloudScanner), which provides concurrency control via distributed locks and a pending action queue. If a scanner already has a running workflow, the reinstall is queued and executed when the current workflow completes.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/batch/reinstall" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"scanners": [
{ "configID": "cfg-scanner-001", "cloudProvider": "aws" },
{ "configID": "cfg-scanner-002", "cloudProvider": "aws" }
]
}'
Response (202 Accepted)
{
"jobId": "ri-scan-550e8400-e29b-41d4-a716-446655440000",
"statusUrl": "/api/v1/jobs?parent-id=ri-scan-550e8400-e29b-41d4-a716-446655440000",
"jobInfo": {
"results": [
{
"configID": "cfg-scanner-001",
"cloudProvider": "aws",
"success": true,
"status": "dispatched"
},
{
"configID": "cfg-scanner-002",
"cloudProvider": "aws",
"success": true,
"status": "dispatched"
}
]
}
}
Response Headers:
Location: /api/v1/jobs?parent-id={jobId}- URL to poll for aggregated statusRetry-After: 30- Recommended polling interval (seconds)
Per-scanner result fields:
success: true— reinstall acceptedsuccess: false— failed; checkerrorfieldstatus—"dispatched"(accepted for processing) or"error"(validation/config failure)
Note: Unlike batch remove, workflowName is not returned in the initial response because workflows are created asynchronously by the management path. Poll the statusUrl to discover workflows as they appear.
Poll Batch Status
curl -X GET "${HOST}/api/v1/jobs?parent-id=ri-scan-550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer ${TOKEN}"
The response follows the same structure as batch remove status (see above). Workflows appear in the response once the management path has dispatched them. Configs that are queued (another workflow running) will not appear until their workflow is created.
Batch Pause Scanners
Synchronously pauses workers for multiple scanners in parallel.
Each scanner in the batch is processed independently (best-effort) with bounded concurrency (up to 10 in parallel). If one scanner fails, the others continue. The endpoint returns 200 OK once all operations have completed, with per-scanner results indicating success or failure.
This operation only updates the scanner configuration settings — it does not modify cloud infrastructure or resources state.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/batch/pause" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"scanners": [
{ "configID": "cfg-scanner-001", "cloudProvider": "aws" },
{ "configID": "cfg-scanner-002", "cloudProvider": "aws" }
]
}'
Response (200 OK)
{
"results": [
{
"configID": "cfg-scanner-001",
"cloudProvider": "aws",
"success": true,
"workersPaused": true
},
{
"configID": "cfg-scanner-002",
"cloudProvider": "aws",
"success": true,
"workersPaused": true
}
]
}
Per-scanner result fields:
success: true— workers paused successfully (or were already paused)success: false— operation failed; checkerrorfieldworkersPaused— the final state of the scanner's workers (true= paused)error— only present whensuccess: false; describes what went wrong
Note: This is a synchronous endpoint. No polling is required — the response contains the final results for all scanners.
Error Responses
- 400 Bad Request — Invalid JSON body or empty
scannerslist - 403 Forbidden — JWT
org-iddoes not match pathorgID
Batch Unpause Scanners
Synchronously unpauses workers for multiple scanners in parallel.
Follows the same semantics as batch pause — best-effort with bounded concurrency. Returns 200 OK once all operations have completed, with per-scanner results.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/batch/unpause" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"scanners": [
{ "configID": "cfg-scanner-001", "cloudProvider": "aws" },
{ "configID": "cfg-scanner-002", "cloudProvider": "aws" }
]
}'
Response (200 OK)
{
"results": [
{
"configID": "cfg-scanner-001",
"cloudProvider": "aws",
"success": true,
"workersPaused": false
},
{
"configID": "cfg-scanner-002",
"cloudProvider": "aws",
"success": true,
"workersPaused": false
}
]
}
Per-scanner result fields:
success: true— workers unpaused successfully (or were already running)success: false— operation failed; checkerrorfieldworkersPaused— the final state of the scanner's workers (false= running)error— only present whensuccess: false; describes what went wrong
Note: This is a synchronous endpoint. No polling is required — the response contains the final results for all scanners.
Error Responses
- 400 Bad Request — Invalid JSON body or empty
scannerslist - 403 Forbidden — JWT
org-iddoes not match pathorgID
Reinstall Scanner
Asynchronously reinstalls a scanner's cloud infrastructure.
This operation triggers an async workflow to delete and recreate the scanner's resources. It includes built-in concurrency control to prevent multiple simultaneous install/uninstall/update operations on the same configuration.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/management/reinstall?config-id=${CONFIG_ID}" \
-H "Authorization: Bearer ${TOKEN}"
Query Parameters:
config-id(required) - The scanner configuration ID
Request Body: None
Response (200 OK)
The endpoint returns an empty 200 OK response upon successfully initiating the reinstall workflow.
Note: Although the response is 200 OK, the reinstall operation executes asynchronously in the background. Use the Retry-After: 30 header guidance when polling for completion.
Disable Region
Synchronously disables a specific region for a scanner configuration.
This operation updates the organisation settings to remove the region from the enabled regions list. It is idempotent - calling it multiple times returns success even if the region is already disabled.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/scanner/region/disable" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"configId": "'${CONFIG_ID}'",
"cloudProvider": "aws"
}'
Response (200 OK)
{
"message": "Region disabled successfully",
"region": "us-east-1",
"cloudOrganizationId": "o-abc123xyz"
}
Note:
- This operation completes immediately. No polling required.
- The region is extracted from the scanner configuration.
- If the region was already disabled, the message will be "Region already disabled".
Remove Cloud Organisation
Asynchronously removes all scanners in a cloud organisation, then deletes credentials.
Request
curl -X DELETE "${HOST}/api/v1/${ORG_ID}/cloud-organization" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"cloudOrganizationId": "o-abc123xyz",
"cloudProvider": "aws"
}'
Response (202 Accepted)
{
"jobId": "rm-org-o-abc123xyz-1733981200",
"statusUrl": "/api/v1/jobs?parent-id=rm-org-o-abc123xyz-1733981200"
}
Note: This operation may take longer than individual scanner operations as it:
- Discovers all scanners in the organisation
- Removes each scanner (parallel workflows)
- Deletes organisation credentials (after all scanners removed)
Poll Job Status
Because remove-org spawns multiple child scanner-removal workflows, poll using the parent-id query parameter to get aggregated status across all child jobs:
curl -X GET "${HOST}/api/v1/jobs?parent-id=rm-org-o-abc123xyz-1733981200" \
-H "Authorization: Bearer ${TOKEN}"
Status Response:
{
"parentID": "rm-org-o-abc123xyz-1733981200",
"summary": {
"total": 2,
"running": 1,
"completed": 1,
"failed": 0
},
"jobs": [
{
"workflowName": "rm-scan-ucsc-adc88239e1868737-1772552434",
"status": "running",
"configId": "ucsc-adc88239e1868737",
"orgId": "org_mjFogBC37G1l7ERc",
"cloudProvider": "aws",
"region": "us-east-1",
"currentStep": "delete-scanner-config",
"createdAt": "2026-03-03T15:40:35Z",
"updatedAt": "2026-03-03T15:43:02Z"
},
{
"workflowName": "rm-scan-ucsc-188bc9b82e66c7fa-1772552434",
"status": "completed",
"configId": "ucsc-188bc9b82e66c7fa",
"orgId": "org_mjFogBC37G1l7ERc",
"cloudProvider": "aws",
"region": "us-east-2",
"currentStep": "post-status",
"createdAt": "2026-03-03T15:40:36Z",
"updatedAt": "2026-03-03T15:43:00Z"
}
]
}
Response fields:
parentID— the correlation ID from the original remove-org requestsummary— aggregated counts across all child workflows (total,running,completed,failed)jobs— individual scanner-removal workflow statuses, each with the same fields as a single job status response
The operation is complete when summary.running == 0 (all jobs are either completed or failed).
Uninstall Scanner
Asynchronously uninstalls a scanner's cloud infrastructure.
This operation triggers an async workflow to remove the scanner. It includes built-in concurrency control to prevent multiple simultaneous install/uninstall/update operations on the same configuration.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/management/uninstall?config-id=${CONFIG_ID}" \
-H "Authorization: Bearer ${TOKEN}"
Query Parameters:
config-id(required) - The scanner configuration ID
Request Body: None
Response (200 OK)
The endpoint returns an empty 200 OK response upon successfully initiating the uninstall workflow.
Note: Although the response is 200 OK, the uninstall operation executes asynchronously in the background. Use the Retry-After: 30 header guidance when polling for completion.
Disable Scanner
Synchronously disable a scanner's workers.
This operation updates the scanner configuration to pause all workers. It is idempotent — calling it on an already-paused scanner returns success without making changes.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/management/pause?config-id=${CONFIG_ID}" \
-H "Authorization: Bearer ${TOKEN}"
Query Parameters:
config-id(required) - The scanner configuration ID
Request Body: None
Response (200 OK)
{
"message": "workers paused successfully",
"configId": "'${CONFIG_ID}'",
"workersPaused": true
}
If already paused (idempotent):
{
"message": "workers already paused",
"configId": "'${CONFIG_ID}'",
"workersPaused": true
}
Note: This operation completes immediately. No polling required.
Unpause Scanner
Synchronously unpauses a scanner's workers.
This operation updates the scanner configuration to resume all workers. It is idempotent — calling it on an already-running scanner returns success without making changes. Workers scale back up based on the job queue after unpausing.
Request
curl -X POST "${HOST}/api/v1/${ORG_ID}/management/unpause?config-id=${CONFIG_ID}" \
-H "Authorization: Bearer ${TOKEN}"
Query Parameters:
config-id(required) - The scanner configuration ID
Request Body: None
Response (200 OK)
{
"message": "workers unpaused successfully",
"configId": "'${CONFIG_ID}'",
"workersPaused": false
}
If already unpaused (idempotent):
{
"message": "workers already unpaused",
"configId": "'${CONFIG_ID}'",
"workersPaused": false
}
Note: This operation completes immediately. No polling required.
Remove Cloud Provider
Asynchronously removes all cloud organisations for a given cloud provider.
This operation discovers all cloud organisation IDs for the specified organisation and cloud provider, then submits one remove-org workflow per organisation. Each workflow removes all scanners in that organisation before deleting the organisation credentials.
The handler uses best-effort submission — if one workflow fails to submit, it continues with the rest and returns all results (a mix of successes and failures).
Request
curl -X DELETE "${HOST}/api/v1/${ORG_ID}/cloud-provider/${CLOUD_PROVIDER}" \
-H "Authorization: Bearer ${TOKEN}"
Path Parameters:
orgID(required) - Organisation ID (must match JWT claim)cloudProvider(required) - Cloud provider name:aws,azure,gcp, ororacle
Request Body: None
Response (202 Accepted)
{
"jobId": "rm-cp-aws-550e8400-e29b-41d4-a716-446655440000",
"statusUrl": "/api/v1/jobs?parent-id=rm-cp-aws-550e8400-e29b-41d4-a716-446655440000",
"jobInfo": {
"results": [
{
"cloudOrganizationId": "o-abc123xyz",
"success": true,
"workflowName": "rm-org-o-abc123xyz-1733981200"
},
{
"cloudOrganizationId": "o-def456uvw",
"success": true,
"workflowName": "rm-org-o-def456uvw-1733981201"
}
]
}
}
Response Headers:
Location: /api/v1/jobs?parent-id={jobId}- URL to poll for statusRetry-After: 30- Recommended polling interval (seconds)
Important:
- The
jobInfo.resultsarray shows immediate submission results for each cloud organisation success: truemeans the workflow was submitted successfully (not that removal completed)success: falsemeans the workflow could not be submitted — check theerrorfield for details- Poll the
statusUrlto track overall progress
Error Responses
- 400 Bad Request - Invalid
cloudProvidervalue - 404 Not Found - No cloud organisations found for this provider
Quick Reference
| Endpoint | Method | Operation Type | Response Code | Poll Required? |
|---|---|---|---|---|
/scanner/remove | POST | Async | 202 Accepted | Yes |
/scanner/batch/remove | POST | Async (batch) | 202 Accepted | Yes |
/scanner/batch/reinstall | POST | Async (batch) | 202 Accepted | Yes |
/scanner/batch/pause | POST | Sync (batch) | 200 OK | No |
/scanner/batch/unpause | POST | Sync (batch) | 200 OK | No |
/management/reinstall | POST | Async | 200 OK | Yes |
/scanner/region/disable | POST | Sync | 200 OK | No |
/cloud-organization | DELETE | Async | 202 Accepted | Yes |
/cloud-provider/{cloudProvider} | DELETE | Async | 202 Accepted | Yes |
/management/uninstall | POST | Async | 200 OK | Yes |
/management/pause | POST | Sync | 200 OK | No |
/management/unpause | POST | Sync | 200 OK | No |
/jobs/{jobId} | GET | Status Check | 200 OK | N/A |
/jobs?parent-id={parentId} | GET | Batch Status | 200 OK | N/A |
Error Responses
All endpoints may return standard error responses:
400 Bad Request
{
"error": "configId is required"
}
401 Unauthorised
{
"error": "Unauthorised"
}
403 Forbidden
{
"error": "Access denied"
}
404 Not Found
{
"error": "Config not found"
}
500 Internal Server Error
{
"error": "Internal server error"
}
Best Practices
Polling Strategy
For async operations:
- Wait at least 30 seconds between poll requests (honour the
Retry-Afterheader) - Implement exponential backoff for long-running operations
- Set a reasonable timeout (15-20 minutes for scanner operations)
- Handle
failedstatus gracefully and check theerrorfield for details
Batch Operations
- Use batch endpoints when operating on multiple scanners to get a single correlation ID (async) or aggregated results (sync)
- Check individual
resultsin the response — some scanners may fail whilst others succeed - For batch reinstall, workflows appear in the status endpoint asynchronously; poll until
summary.totalmatches the expected count - Configs with an already-running workflow will be queued and processed after the current workflow completes
- Batch pause/unpause are synchronous — the response is final with no polling needed
Error Handling
- 400 Bad Request: Validate your request payload before retrying
- 401 Unauthorised: Refresh your JWT token
- 403 Forbidden: Verify your JWT org-id matches the path parameter
- 404 Not Found: The scanner config doesn't exist or was already deleted
- 500 Internal Server Error: Retry with exponential backoff (3-5 attempts)