---
title: "Start a Discovery Session"
method: POST
path: "/api/v1/discovery/start-session"
tags: ["Discoveries"]
---

# Start a Discovery Session

`POST /api/v1/discovery/start-session`

## Response `200`

Discovery session started

- ApiResponseDiscoveryUpdatePayload
  - `data` object — Progress update from daemon to server during discovery
    - `daemon_id` string, uuid, required
    - `discovery_id` string, uuid, nullable — The discovery configuration this session belongs to. Always enriched server-side; daemons do not send this field.
    - `discovery_type` union, required
      - object
        - `host_id` string, uuid, required
        - `type` 'SelfReport', required
      - object
        - `host_naming_fallback` 'Ip' | 'BestService', required
        - `snmp_credentials` object — SNMP credentials for querying devices during discovery Server builds this mapping before initiating discovery
        - `subnet_ids` string[], nullable, required
        - `type` 'Network', required
      - object
        - `host_id` string, uuid, required
        - `host_naming_fallback` 'Ip' | 'BestService', required
        - `type` 'Docker', required
      - object
        - `host_id` string, uuid, required — ID of the host that the daemon is running on
        - `host_naming_fallback` 'Ip' | 'BestService', required
        - `scan_settings` ScanSettings — Scan performance settings. Lives on the discovery entity. Numeric fields are `Option<T>` — `None` means "use daemon default". The daemon unwraps with defaults at point of use.
          - `arp_rate_pps` integer, nullable — ARP packets per second (default: 50)
          - `arp_retries` integer, nullable — ARP retry rounds for non-responsive targets (default: 2 = 3 total attempts)
          - `arp_scan_cutoff` integer, nullable — ARP scan cutoff prefix. Interfaced subnets larger than this prefix are truncated to this many IPs. Default: 15 (= /15, ~131K IPs). Lower values scan more IPs — increase arp_rate_pps accordingly.
          - `full_scan_interval` integer, nullable — Run a full 65k port scan every N scans. Other scans use a light port set. Default: 3. Value of 0 means never full scan. Value of 1 means every scan is full.
          - `is_full_scan` boolean — Whether this specific scan run should do a full 65k port scan. Set by the server before dispatching to the daemon — not user-configurable.
          - `max_discovery_duration` integer, nullable — Hard ceiling on how long a single discovery run may take, in seconds (default: 21600 = 6h). When hit, the run force-completes and any hosts still queued are left un-scanned until the next run. Raise this for very large networks that legitimately need more than the default window.
          - `port_scan_batch_size` integer, nullable — Ports scanned concurrently per host (default: 200, clamped 16-1000)
          - `probe_raw_socket_ports` boolean — Whether to probe raw-socket ports 9100-9107 (default: false). Disabled by default to prevent ghost printing on JetDirect printers.
          - `scan_rate_pps` integer, nullable — Port scan probes per second (default: 500)
          - `use_npcap_arp` boolean — On Windows, use Npcap broadcast ARP instead of SendARP (default: false)
        - `subnet_ids` string[], nullable, required — Subnets to scan. None = scan all interfaced subnets.
        - `type` 'Unified', required
    - `error` string, nullable
    - `estimated_remaining_secs` integer, nullable
    - `finished_at` string, date-time, nullable
    - `hosts_discovered` integer, nullable
    - `network_id` string, uuid, required
    - `phase` 'AwaitingSnapshot' | 'Queued' | 'Pending' | 'Starting' | 'Started' | 'Scanning' | 'Complete' | 'Failed' | 'Cancelled', required
    - `progress` integer, required
    - `scanned` ScannedEntityIds — Canonical IDs of entities scanned in a discovery session. Populated daemon-side at terminal phase from `EntityBuffer`'s `Created` entries. Travels with the terminal `DiscoveryUpdatePayload` to the server, rides the in-memory `EntityOperation::Created` event published for the historical Discovery row (the event scope carries `Entity::Discovery` with the full struct, including `run_type::Historical { results }`), then is stripped before persisting into the historical Discovery row's JSONB (see the `SqlValue::RunType` bind_value handler in `backend/src/server/shared/storage/generic.rs`). Per-entity-service subscribers extract `results.scanned` from the in-memory event and call `DiscoveryFkUpdater::update_discovery_fks` to backfill `last_discovery_id` / `first_discovery_id` on the matched rows. Naming: `scanned_*` because the daemon scans entities — some submissions match existing rows (refresh), others insert new rows. Both populate the EntityBuffer with canonical (server-assigned) IDs.
      - `binding_ids` string[]
      - `host_ids` string[]
      - `interface_ids` string[]
      - `ip_address_ids` string[]
      - `port_ids` string[]
      - `service_ids` string[]
      - `subnet_ids` string[]
      - `vlan_ids` string[]
    - `session_id` string, uuid, required
    - `started_at` string, date-time, nullable
    - `warnings` string[] — Non-fatal warnings for a completed run (e.g. the scan hit its time limit and left hosts un-scanned). Unlike `error`, these do not mark the run failed.
  - `error` string, nullable
  - `meta` ApiMeta, required — API metadata included in all responses
    - `api_version` integer, required — API version (integer, increments on breaking changes)
    - `server_version` string, required — Server version (semver)
  - `success` boolean, required

## Other responses

- `404` — Discovery not found
- `409` — A session is already running for this discovery

## Changes

- **2026-07-20** `9f94dcfb4631` — 2 info
  - added the optional property `data/discovery_type/oneOf[subschema #4: Unified]/scan_settings/max_discovery_duration` to the response with the `200` status
  - added the optional property `data/warnings` to the response with the `200` status
- **2026-05-03** `d38c20597ec1` — 1 warning, 1 info
  - added the new `AwaitingSnapshot` enum value to the `data/phase` response property for the response status `200`
  - added the optional property `data/scanned` to the response with the `200` status
- **2026-04-20** `f04499e2280f` — 1 warning, 1 info
  - removed the optional property `data/scanned` from the response with the `200` status
  - removed the `AwaitingSnapshot` enum value from the `data/phase` response property for the response status `200`

[Change history](https://skmtc.dev/scanopy/apis/scanopy-api/changes/api/v1/discovery/start-session/post.md)

---

[API](https://skmtc.dev/scanopy/apis/scanopy-api.md) · [All operations](https://skmtc.dev/scanopy/apis/scanopy-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/scanopy/scanopy-api/revisions/bd76f90aa44b/schema)
