ScanopyScanopy
Networking & Deployment

Automate a site rollout

Create a site, install its daemon, and share its topology with the Scanopy API.

Rolling out a new site takes the same API calls each time: create the site, provision a daemon, install it on a host at the site, wait for the first discovery, and share the topology. Every call uses one API key, so a script or a remote management tool can run the whole sequence.

Each step shows the request fields it uses, taken from the API specification. The link on each call opens its full reference, with the response and example requests.

Prerequisites

  • A plan that includes API access and share links. See pricing.
  • An API key created in Platform > API Keys by an organization Admin or Owner, with the Admin permission level and All sites. Admin is the level that can create sites and daemons, and All sites gives the key every site it creates. A key never exceeds its creator's access, as API keys describes.
  • Root access, or passwordless sudo, on a host at the new site, and a way to run commands on it.
  • On a server that sends email, a verified email on an organization owner's account. Until an owner verifies, the organization can run one daemon.

Send each request with the key as a bearer token, as Authentication shows.

1. Create the site

POST/api/v1/sitesCreate site
FieldInTypeDescription
name requiredbodystringHuman-facing name for this site.

Keep the new site's id. The site's topology is created with it.

2. Provision the daemon

Provisioning creates the daemon's record on the site and mints the key the daemon authenticates with.

POST/api/v1/daemons/provisionProvision or re-provision daemon
FieldInTypeDescription
namebodystringHuman-readable name for the daemon. Required unless daemon_id is set, in which case the existing record's name is kept.
site_idbodyuuidSite this daemon will be associated with. Required unless daemon_id is set, in which case the existing record's site is kept.
modebodyone of server_poll, daemon_pollHow the daemon communicates with the server. Defaults to DaemonPoll (the daemon dials out) for forward-compat with older clients.
urlbodystringReachable URL where the server can dial the daemon. Required for ServerPoll, unused for DaemonPoll (the daemon dials out instead).
seed_credential_refsbodyIntegrationTarget[]Credential/integration references to seed onto the daemon's first discovery run. References only — never secret material. Empty by default.

In daemon_poll mode the daemon opens the connection to the server, so the site needs no inbound port. Choosing a polling mode covers both modes.

From the response, keep the daemon record's id, and store daemon_api_key. This response is the only place the key appears.

3. Install the daemon

GET/api/v1/daemons/{id}/install-commandGenerate daemon install command
FieldInTypeDescription
id requiredpathuuiddaemon ID
purpose requiredqueryone of install, rekey, reconfigureinstall or rekey (with the api-key placeholder), or reconfigure (credential-free).

Set purpose to install. The response holds a command for each platform, such as linux and windows, and a Docker setup in docker. The API key in each is a placeholder: replace it with the key you stored in step 2. For Docker, replace it in both compose and env.

Run the command as root on the host. It asks no questions, installs the daemon as a service, and starts it. To run it again on a host that already has a daemon, see Setting up multiple daemons.

4. Wait for the daemon to connect

GET/api/v1/daemons/{id}Get daemon by ID
FieldInTypeDescription
id requiredpathuuidDaemon ID

Poll until health is no longer awaiting_connection.

5. Wait for the first discovery

The daemon starts its first discovery when it connects. Each discovery that finishes is recorded as a completed run.

GET/api/v1/discoveriesList discoveries
FieldInTypeDescription
daemon_idsqueryuuid[]Filter by daemon ID. Repeat the parameter to pass several.
historicalquerybooleantrue returns only completed runs (the history view), false only the configurations that produce them. Omit for both.
phasesqueryone of AwaitingSnapshot, Queued, Pending, Starting, Started, Scanning, Complete, Failed, Cancelled[]Only runs that ended in one of these phases (run_type.results.phase). Repeat for several. Configurations, which have no recorded outcome, never match.

Poll with the daemon's id and historical set to true until a run appears. A run in Complete has populated the topology. A run in Failed or Cancelled has not; Troubleshooting scans covers the causes.

6. Share the topology

Find the site's topology:

GET/api/v1/topologiesList topologies
FieldInTypeDescription
site_idqueryuuidFilter by site ID

Keep the topology's id, and create a share for it:

POST/api/v1/sharesCreate share
FieldInTypeDescription
share.topology_id requiredbodyuuidThe topology this share exposes.
share.site_id requiredbodyuuidThe site this entity belongs to.
share.name requiredbodystringHuman-facing name for this share.
share.is_enabled requiredbodybooleanWhether the link still resolves. Disabled shares return 404.
share.options requiredbodyShareOptionsWhat the viewer can see and do.
share.enabled_views requiredbodyone of L2Physical, L3Logical, Workloads, Application[]Which topology views are enabled for this share. None = all views (subject to data availability). Some(list) = only these views in order. First element is the default view shown on load.
share.passwordbodystringPlaintext password on ingest; redacted sentinel ("********") or None on egress. Never stored — password_hash is the DB column. Wrapped in SecretString so Debug/logging shows [REDACTED] during the window between request deserialization and hashing.
share.expires_at requiredbodystringWhen this record stops being valid.
share.allowed_domains requiredbodystring[]Domains permitted to embed this share. Empty means no restriction.

To embed the topology on another site, list that site's hostname in allowed_domains. A share with a password asks each visitor for it, including inside an embed.

The share's response carries its id but no URL. Build the link or embed address from the id, as Share URLs describes.

Product names and logos are trademarks of their respective owners. See credits.

On this page