Skip to main content

Chunked scan upload

The Start Scan API uploads large codebases across multiple requests. BLAST scanning must be enabled for your company, and you upload a single source archive. Use this guide for the upload sequence. Request fields and status codes live on the OpenAPI pages for POST /start-scan, PATCH /start-scan/{transfer_id}/, and HEAD /start-scan/{transfer_id}/.

Upload sequence

  1. Start the transfer with POST /start-scan. Send scan_type=blast as a form field and a files part that includes the archive name and an empty body. The archive name must use one of .zip, .tar, .json, .fpr, .sarif, or .xml. The response includes a transfer_id.
  2. Read the current offset with HEAD /start-scan/{transfer_id}/. The Upload-Offset response header is the next byte to send. An unknown or empty transfer returns 0.
  3. Upload each chunk with PATCH /start-scan/{transfer_id}/. Send the next bytes as chunk_data, and include these request headers:
    • Upload-Offset: current byte offset
    • Upload-Length: total file size in bytes
    • Upload-Name: archive file name
  4. Finish when the last PATCH returns scan_id. Intermediate PATCH responses include Upload-Offset (the next byte) and do not include scan_id. When the last chunk completes the archive, the JSON body includes scan_id and project_id. That completing response does not set Upload-Offset. Use scan_id with the scan and issue APIs. HEAD does not return scan_id.
You can also send project_name, branch, repo_url, sha, files_to_scan, dirty, scan_configs, and target_policies on each PATCH request. Omit partial_scan for a full scan. Send partial_scan=true only for a partial scan.

Authentication

Include your API token on every request:

Scan metadata

metadata is an optional JSON object string, for example {"pipeline_url": "https://ci.example/run/123"}. Corgea validates it on every chunk request and attaches it to the scan when the upload completes, so send the same value with each chunk. The object must be at most 16,384 bytes.

Python example

This script starts a BLAST upload or resumes one with --transfer_id. It follows Upload-Offset on intermediate chunks. The last PATCH returns scan_id instead of Upload-Offset.
Example:
To resume an interrupted upload, pass the existing transfer ID:
For a partial scan, add --partial_scan and --files_to_scan "vuln.py,test.py". To attach scan metadata, add --metadata '{"pipeline_url":"https://ci.example/run/123"}'. The same value is sent with every chunk.