arazzo: 1.0.1 info: title: Shodan Submit On-Demand Scan and Poll summary: Submit an on-demand scan and poll its status until the crawl completes. description: >- The core on-demand scanning pattern. The workflow first confirms there are scan credits available, submits a crawl request for the supplied IPs or CIDR ranges, then polls the scan status endpoint until the scan reaches the DONE state. Every step spells out its request inline so the flow can be read and executed without opening the underlying OpenAPI description. version: 1.0.0 sourceDescriptions: - name: shodanRest url: ../openapi/shodan-rest-openapi.yml type: openapi workflows: - workflowId: submit-scan-and-poll summary: Submit an on-demand scan and wait for it to finish. description: >- Verifies scan credits, submits the crawl request, and polls the scan status endpoint, looping until the scan status is DONE. inputs: type: object required: - apiKey - ips properties: apiKey: type: string description: Shodan API key passed as the `key` query parameter. ips: type: string description: Comma-separated list of IPs or CIDR ranges to crawl. steps: - stepId: checkCredits description: >- Confirm the account has scan credits remaining before submitting the crawl request. operationId: getApiInfo parameters: - name: key in: query value: $inputs.apiKey successCriteria: - condition: $statusCode == 200 - context: $response.body condition: $.scan_credits > 0 type: jsonpath outputs: scanCredits: $response.body#/scan_credits - stepId: submitScan description: >- Request Shodan to crawl the supplied IPs or netblocks. Each IP consumes one scan credit. operationId: createScan requestBody: contentType: application/x-www-form-urlencoded payload: ips: $inputs.ips parameters: - name: key in: query value: $inputs.apiKey successCriteria: - condition: $statusCode == 200 outputs: scanId: $response.body#/id status: $response.body#/status - stepId: pollScan description: >- Poll the scan status endpoint and repeat until the scan reaches the DONE state. operationId: getScan parameters: - name: key in: query value: $inputs.apiKey - name: id in: path value: $steps.submitScan.outputs.scanId successCriteria: - condition: $statusCode == 200 outputs: status: $response.body#/status count: $response.body#/count onSuccess: - name: scanComplete type: end criteria: - context: $response.body condition: $.status == "DONE" type: jsonpath - name: scanStillRunning type: goto stepId: pollScan criteria: - context: $response.body condition: $.status != "DONE" type: jsonpath outputs: scanId: $steps.submitScan.outputs.scanId finalStatus: $steps.pollScan.outputs.status count: $steps.pollScan.outputs.count