ServerScan API

Read and manage your PCI ASV scanning from your own systems.

Authentication. Use your Scan Manager User Token. In Scan Manager, open Access Token and generate a User Token, then send it as Authorization: Bearer <token>. That one token is all you need: you create, replace and revoke it in Scan Manager, and a revoked token stops working here on the next call. Send the User Token, not the API Key shown on the same page. Tokens are never accepted in the query string, and browser sessions are refused. The examples read your token from a SCANMANAGER_TOKEN environment variable.

Paging. Collections take limit (1 to 100, default 25) and return next_cursor. Pass it back as cursor until it is null.

Limits. Each account can make 100 calls a minute and 3,000 calls an hour, whichever token it uses. Both limits are rolling: a call counts for the 60 minutes after it is made, not until the clock reaches the hour. There is no daily limit. Over either one, the answer is 429 rate_limited with a Retry-After header: the number of seconds until your next call will be accepted. Refused calls do not count.

Each IP address can also send about 5 calls a second, with short bursts of up to 30. Faster than that, the answer is a 429 with no Retry-After. Wait a second and slow down.

Wait for Retry-After rather than retrying at once. An address that keeps getting 401 or 429 answers can be blocked from the API for an hour. When you wait for a report document, check every 10 seconds or so. Checking in a tight loop spends your limit.

Base URL: https://www.serverscan.com/api/v1.

Targets

List your scan targets.

GET /targets

Parameters

limit
query
integer
cursor
query
string
next_cursor from the previous page, passed back unchanged.
curl "https://www.serverscan.com/api/v1/targets" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
            "...": ""
        }
    ],
    "next_cursor": null
}

Register a scan target.

POST /targets

Body application/json

name string
hosts string
comment string
curl -X POST "https://www.serverscan.com/api/v1/targets" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main storefront","hosts":"shop.example.com","comment":"Quarterly external scan"}'

Example response

HTTP/1.1 201 Created
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

How many more targets your license allows.

GET /targets/allow

curl "https://www.serverscan.com/api/v1/targets/allow" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Read one target.

GET /targets/{uuid}

Parameters

uuid
path, required
string (uuid)
curl "https://www.serverscan.com/api/v1/targets/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Change a target.

PATCH /targets/{uuid}

Send only the fields you want to change. Everything else is kept.

Parameters

uuid
path, required
string (uuid)

Body application/json

name string
hosts string
comment string
curl -X PATCH "https://www.serverscan.com/api/v1/targets/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Main storefront","hosts":"shop.example.com","comment":"Quarterly external scan"}'

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Remove a target.

DELETE /targets/{uuid}

Parameters

uuid
path, required
string (uuid)
curl -X DELETE "https://www.serverscan.com/api/v1/targets/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 204 No Content

Scans

List your scans.

GET /scans

Parameters

limit
query
integer
cursor
query
string
next_cursor from the previous page, passed back unchanged.
curl "https://www.serverscan.com/api/v1/scans" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
            "...": ""
        }
    ],
    "next_cursor": null
}

Create a scan and start it. Uses one license; send an Idempotency-Key.

POST /scans

Requires an Idempotency-Key header. Repeating a key with the same body returns the first answer, marked Idempotent-Replayed: true, instead of creating a second scan.

Parameters

Idempotency-Key
header, required
string

Body application/json

name string
comment string
target_id string (uuid)
schedule_id string (uuid)
notification_ids array of string (uuid)
curl -X POST "https://www.serverscan.com/api/v1/scans" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -H "Idempotency-Key: create-scan-2026-09-18-001" \
  -H "Content-Type: application/json" \
  -d '{"name":"Q4 external scan","comment":"string","target_id":"3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35","schedule_id":"3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35","notification_ids":["3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35"]}'

Example response

HTTP/1.1 201 Created
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35"
    },
    "started": true
}

Read one scan and its status.

GET /scans/{uuid}

Parameters

uuid
path, required
string (uuid)
curl "https://www.serverscan.com/api/v1/scans/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Stop a running scan.

POST /scans/{uuid}/stop

Parameters

uuid
path, required
string (uuid)
curl -X POST "https://www.serverscan.com/api/v1/scans/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35/stop" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

List the reports one scan produced.

GET /scans/{uuid}/reports

Parameters

uuid
path, required
string (uuid)
limit
query
integer
cursor
query
string
next_cursor from the previous page, passed back unchanged.
curl "https://www.serverscan.com/api/v1/scans/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35/reports" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
            "...": ""
        }
    ],
    "next_cursor": null
}

Schedules

List your schedules.

GET /schedules

Parameters

limit
query
integer
cursor
query
string
next_cursor from the previous page, passed back unchanged.
curl "https://www.serverscan.com/api/v1/schedules" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
            "...": ""
        }
    ],
    "next_cursor": null
}

Create a schedule.

POST /schedules

Body application/json

name string
comment string
first_time string
period string
period_unit string
duration string
duration_unit string
timezone string
byday string
bymonthday string
curl -X POST "https://www.serverscan.com/api/v1/schedules" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Quarterly","comment":"string","first_time":"string","period":"string","period_unit":"string","duration":"string","duration_unit":"string","timezone":"string","byday":"string","bymonthday":"string"}'

Example response

HTTP/1.1 201 Created
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

The values a schedule accepts.

GET /schedules/options

curl "https://www.serverscan.com/api/v1/schedules/options" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Read one schedule.

GET /schedules/{uuid}

Parameters

uuid
path, required
string (uuid)
curl "https://www.serverscan.com/api/v1/schedules/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Change a schedule.

PATCH /schedules/{uuid}

Send only the fields you want to change. Everything else is kept.

Parameters

uuid
path, required
string (uuid)

Body application/json

name string
comment string
first_time string
period string
period_unit string
duration string
duration_unit string
timezone string
byday string
bymonthday string
curl -X PATCH "https://www.serverscan.com/api/v1/schedules/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Quarterly","comment":"string","first_time":"string","period":"string","period_unit":"string","duration":"string","duration_unit":"string","timezone":"string","byday":"string","bymonthday":"string"}'

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Remove a schedule.

DELETE /schedules/{uuid}

Parameters

uuid
path, required
string (uuid)
curl -X DELETE "https://www.serverscan.com/api/v1/schedules/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 204 No Content

Reports

A report is one finished scan. Read its findings from GET /reports/{uuid}/vulnerabilities, one row per finding, ready for a vulnerability dashboard. Its documents are three PDFs and a spreadsheet, which you ask for and then download:

TypeDocumentWho it is for
detailedThe full scan report, with every finding. The default.Your team, to fix what the scan found.
attestationThe Attestation of Scan Compliance. It shows whether the scan passed.Your acquirer or bank.
executiveThe executive summary.Management.
remediationThe vulnerability spreadsheet (.xlsx): every finding with its fix, a worksheet to track fixes, and the hosts scanned.Your team, to track fixes.

Getting a document.

  1. Ask for it: POST /reports/{uuid}/generate?type=attestation.
  2. Wait until it is ready. GET /reports/{uuid} lists each document under files, by type. Its status is processing while it is being made and done when it is ready. That usually takes a few seconds. Check every 10 seconds or so, not in a tight loop.
  3. Download it: GET /reports/{uuid}/pdf?type=attestation for a PDF, or GET /reports/{uuid}/xlsx for the spreadsheet.
"files": {
  "detailed": { "status": "done", ... },
  "attestation": { "status": "processing", ... }
}

Asking again makes the document again, and it cannot be downloaded while it is being made. If its status is failed, ask again. Until a document is ready, the download answers 404 not_found with a message saying why. files can also list documents made in Scan Manager that this API does not offer.

List your reports.

GET /reports

Parameters

limit
query
integer
cursor
query
string
next_cursor from the previous page, passed back unchanged.
curl "https://www.serverscan.com/api/v1/reports" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
            "...": ""
        }
    ],
    "next_cursor": null
}

Read one report.

GET /reports/{uuid}

Includes files: each document made for this report, with its status. See Report documents.

Parameters

uuid
path, required
string (uuid)
curl "https://www.serverscan.com/api/v1/reports/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "name": "2026-09-25T14:02:11.000-04:00",
        "scan_run_status": "Done",
        "creation_time": "2026-09-25T14:02:19.000-04:00",
        "end_time": "2026-09-25T14:41:07.000-04:00",
        "results_count": {
            "high": 0,
            "medium": 3,
            "low": 2
        },
        "files": {
            "detailed": {
                "type": "detailed",
                "status": "done",
                "filename": "detailed-3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35.pdf",
                "created_at": "2026-09-26T20:28:53.908Z",
                "updated_at": "2026-09-26T21:21:43.203Z"
            },
            "attestation": {
                "type": "attestation",
                "status": "processing",
                "filename": "attestation-3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35.pdf",
                "created_at": "2026-09-26T20:28:55.120Z",
                "updated_at": "2026-09-26T21:56:32.156Z"
            }
        },
        "...": ""
    }
}

Read one report in full, findings included.

GET /reports/{uuid}/details

The report as the scanning platform keeps it, every finding included under results. For the findings as a flat list, one row each, use /vulnerabilities. For the PDFs, see Report documents.

Parameters

uuid
path, required
string (uuid)
curl "https://www.serverscan.com/api/v1/reports/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35/details" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Ask for a report document to be generated.

POST /reports/{uuid}/generate

Starts making one document. Ask once for each type you want. See Report documents for the four types and how to tell when one is ready.

Parameters

uuid
path, required
string (uuid)
type
query
string
Which document. See Report documents. Any other value is 422 invalid_request.

One of:

  • detailed default The full scan report, with every finding.
  • attestation The Attestation of Scan Compliance, for your acquirer or bank.
  • executive The executive summary.
  • remediation The vulnerability spreadsheet (.xlsx), downloaded from /reports/{uuid}/xlsx.
curl -X POST "https://www.serverscan.com/api/v1/reports/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35/generate?type=attestation" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": []
}

Download a report document as a PDF.

GET /reports/{uuid}/pdf

Downloads a document once it is ready. See Report documents. Before then this answers 404 not_found, with a message saying why.

Parameters

uuid
path, required
string (uuid)
type
query
string
Which PDF. See Report documents. Any other value is 422 invalid_request.

One of:

  • detailed default The full scan report, with every finding.
  • attestation The Attestation of Scan Compliance, for your acquirer or bank.
  • executive The executive summary.
curl "https://www.serverscan.com/api/v1/reports/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35/pdf?type=attestation" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -o attestation.pdf

Example response

HTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: attachment; filename="serverscan-attestation-3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35.pdf"

%PDF-1.7 ...

Download the vulnerability spreadsheet (.xlsx).

GET /reports/{uuid}/xlsx

Every finding with its fix, a worksheet to track fixes, and the hosts scanned. Generate it first with type=remediation: see Report documents. Before then this answers 404 not_found, with a message saying why.

Parameters

uuid
path, required
string (uuid)
curl "https://www.serverscan.com/api/v1/reports/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35/xlsx" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -o remediation.xlsx

Example response

HTTP/1.1 200 OK
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Content-Disposition: attachment; filename="serverscan-remediation-3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35.xlsx"

(the workbook)

List one report's vulnerabilities, one row per finding.

GET /reports/{uuid}/vulnerabilities

Every finding in one report, worst first, one row each. Built for feeding a vulnerability dashboard: list your reports with GET /reports, then read this once for each new report.

Log entries are left out unless you ask for them with min_level=log. They are the scanner's notes, such as which ports were open, at severity 0. meta.counts counts every finding in the report by level, whatever min_level you ask for.

Each row has:

  • id: this finding. It is new every scan.
  • oid: the check that found it. It is the same in every scan, so host, port and oid together follow one issue from scan to scan.
  • host, port, protocol: where it was found. port is null for a finding about the host as a whole.
  • name: the finding's title. family: the kind of check.
  • severity: the CVSS base score, 0 to 10. cvss_vector: the CVSS base vector.
  • level: high (7.0 and up), medium (4.0 to 6.9), low (0.1 to 3.9) or log (0).
  • cves: CVE ids. Often empty: many checks, such as a missing security header, have none.
  • qod: how sure the scanner is, 0 to 100.
  • summary, insight, affected, impact, detection: what the finding is, why it matters, what is affected, and how it was found.
  • solution, solution_type: how to fix it.
  • evidence: what the scanner saw on this host.
  • references: links about the finding.
  • report_id, scan_id, scanned_at: the report and scan it came from, and when the scan finished, in UTC.

Any text field can be null when the check does not provide it.

Parameters

uuid
path, required
string (uuid)
min_level
query
string
The lowest level to include. Any other value is 422 invalid_request.

One of:

  • log Everything, the scanner's log entries included.
  • low default Every vulnerability, scored 0.1 and up.
  • medium Scored 4.0 and up.
  • high Scored 7.0 and up.
curl "https://www.serverscan.com/api/v1/reports/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35/vulnerabilities" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "b25b6797-995a-441b-9d1c-5543705bc422",
            "report_id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
            "scan_id": "4a0b2c88-cbbb-4985-a2a2-1d9030b58086",
            "scanned_at": "2026-09-25T18:41:07Z",
            "host": "203.0.113.10",
            "port": 443,
            "protocol": "tcp",
            "name": "SSL/TLS: HTTP Strict Transport Security (HSTS) Missing or Misconfigured",
            "severity": 6.5,
            "level": "medium",
            "cvss_vector": "AV:N/AC:L/Au:S/C:P/I:P/A:P",
            "cves": [],
            "oid": "1.3.6.1.4.1.25623.1.0.300216",
            "family": "Web vulnerability",
            "qod": 100,
            "summary": "The remote web server is not enforcing HTTP Strict Transport Security (HSTS).",
            "insight": null,
            "affected": null,
            "impact": null,
            "detection": null,
            "solution": "Enable HSTS or configure the required directives correctly following RFC 6797 and security best practices.",
            "solution_type": "Mitigation",
            "evidence": "The remote web server is not enforcing HSTS.",
            "references": [
                "https://owasp.org/www-project-secure-headers/"
            ]
        }
    ],
    "meta": {
        "report_id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "scan_id": "4a0b2c88-cbbb-4985-a2a2-1d9030b58086",
        "status": "Done",
        "scanned_at": "2026-09-25T18:41:07Z",
        "hosts_scanned": 1,
        "min_level": "low",
        "counts": {
            "high": 0,
            "medium": 3,
            "low": 2,
            "log": 30
        }
    }
}

Exceptions

List the exceptions you have raised.

GET /exceptions

Parameters

limit
query
integer
cursor
query
string
next_cursor from the previous page, passed back unchanged.
curl "https://www.serverscan.com/api/v1/exceptions" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
            "...": ""
        }
    ],
    "next_cursor": null
}

Read one exception.

GET /exceptions/{uuid}

Parameters

uuid
path, required
string (uuid)
curl "https://www.serverscan.com/api/v1/exceptions/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Withdraw an exception.

DELETE /exceptions/{uuid}

Parameters

uuid
path, required
string (uuid)
curl -X DELETE "https://www.serverscan.com/api/v1/exceptions/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 204 No Content

Notifications

List your notification rules.

GET /notifications

Parameters

limit
query
integer
cursor
query
string
next_cursor from the previous page, passed back unchanged.
curl "https://www.serverscan.com/api/v1/notifications" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
            "...": ""
        }
    ],
    "next_cursor": null
}

Create a notification rule.

POST /notifications

Body application/json

name string
to_address string
status_changed string
severity_at_least string
curl -X POST "https://www.serverscan.com/api/v1/notifications" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Security team","to_address":"[email protected]","status_changed":"string","severity_at_least":"string"}'

Example response

HTTP/1.1 201 Created
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Change a notification rule.

PATCH /notifications/{uuid}

Send only the fields you want to change. Everything else is kept.

Parameters

uuid
path, required
string (uuid)

Body application/json

name string
to_address string
status_changed string
severity_at_least string
curl -X PATCH "https://www.serverscan.com/api/v1/notifications/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Security team","to_address":"[email protected]","status_changed":"string","severity_at_least":"string"}'

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": {
        "id": "3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35",
        "...": ""
    }
}

Remove a notification rule.

DELETE /notifications/{uuid}

Parameters

uuid
path, required
string (uuid)
curl -X DELETE "https://www.serverscan.com/api/v1/notifications/3f2c8a1e-5b7d-4c9e-9a61-2d4e8f0b7c35" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 204 No Content

License

When your scanning license renews or expires, one row per subscription.

GET /license

Your scanning license, one row per subscription, soonest to expire first. For how many hosts you are scanning now, use GET /targets/allow.

Each row has:

  • id: this subscription.
  • plan: what was bought. term: how often it renews, one of quarterly, one_year, two_year or three_year.
  • domain: the website or host named when it was bought, or null.
  • hosts: how many hosts it covers.
  • status: see the table below. renews: true when it will renew on its own.
  • started_at: when it began, in UTC.
  • expires_at: when the paid period ends, in UTC. For an active row, this is also the renewal date.
StatusWhat it means
activePaid up. It renews on its own at expires_at.
past_dueA renewal payment failed. It is paid through expires_at. Update the card in your ServerScan account to renew it. If it stays unpaid, it is canceled.
canceledIt will not renew. Scans keep running until expires_at.
expiredIt ended at expires_at. Listed only with include=expired.

meta has:

  • licensed_hosts: the hosts your license covers right now.
  • next_expires_at: the soonest expires_at still to come, or null.
  • counts: your subscriptions by status, expired ones included.

An expired license stops new scans, not this API. You can still read your reports and download their documents.

Parameters

include
query
string
Send expired to list expired subscriptions too. meta.counts counts them either way. Any other value is 422 invalid_request.

One of:

  • expired List expired subscriptions as well.
curl "https://www.serverscan.com/api/v1/license" \
  -H "Authorization: Bearer $SCANMANAGER_TOKEN"

Example response

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: 9f1c2e7a4b6d8e03

{
    "data": [
        {
            "id": "6f1d2c3b-8a47-4e0f-9b25-3c7e1a9d4f60",
            "plan": "PCI Scanning Sign-Up",
            "term": "one_year",
            "domain": "shop.example.com",
            "hosts": 1,
            "status": "active",
            "renews": true,
            "started_at": "2025-10-14T16:02:11Z",
            "expires_at": "2026-10-14T16:02:11Z"
        }
    ],
    "meta": {
        "licensed_hosts": 1,
        "next_expires_at": "2026-10-14T16:02:11Z",
        "counts": {
            "active": 1,
            "past_due": 0,
            "canceled": 0,
            "expired": 2
        }
    }
}

Errors

Branch on code, not on message. Codes keep their meaning and status for the life of v1.

StatusCodeMeaning
401missing_tokenSend your Scan Manager User Token as "Authorization: Bearer <token>".
401invalid_tokenThat token was not accepted. Generate a new User Token on the Access Token page in Scan Manager.
403wrong_auth_methodThis API accepts only a bearer token. Browser sessions are refused.
403not_enabledAPI access is not enabled for this account yet.
403forbiddenYou do not have access to this.
403account_blockedThis ServerScan account is closed. Contact support and quote the request id.
403account_not_linkedThat token works in Scan Manager, but it is not linked to a ServerScan account. Contact support and quote the request id.
404not_foundNot found.
405method_not_allowedMethod not allowed on this path.
422invalid_requestThe request is not valid.
415unsupported_media_typeSend the request body as application/json.
413payload_too_largeThe request body is too large.
409idempotency_conflictThat Idempotency-Key was already used with a different request.
409idempotency_in_progressA request with that Idempotency-Key is still being processed.
429rate_limitedToo many requests. Slow down and retry after the Retry-After interval.
502upstream_errorThe scanning platform returned an error. Retry later, and quote the request id if it persists.
504upstream_timeoutThe scanning platform did not answer in time. Retry later.
502upstream_too_largeThe scanning platform returned more data than this API forwards.
500internal_errorSomething went wrong on our side. Quote the request id to support.

Every error

{
  "error": {
    "code": "invalid_token",
    "message": "That token was not accepted. Generate a new User Token on the Access Token page in Scan Manager.",
    "request_id": "9f1c2e7a4b6d8e03"
  }
}