End-to-End Example: Create / Deploy / Update / Delete a Connector

Prev Next

This guide shows a complete, real-world workflow to manage a connector using SSW APIs: create it, get the command that deploys it on your host, change its settings, and delete it.

What You Will Do

  1. Authenticate API key → get sdp_token
  2. Pick an edge and a network → get edge_id and the network name
  3. Create a connector (or look up an existing one) → get site_id
  4. Get the deploy command for Docker / Helm / Linux / Windows / macOS
  5. Update the connector settings
  6. Clean up by deleting the connector

Auth requirement
All /ztna/v1/... API calls require:

Authorization: Bearer <sdp_token>

💡 Tip
In the API, a connector is called a site. site_id is the connector ID.

Prerequisites

Required

API key that can obtain an SDP token. The user who owns the key needs these roles:

Operation Minimum role
Create / update a connector Network Manager
Get the deploy command Admin
Delete a connector Any role (non-managers can only delete connectors they created)

To run every step in this guide, use a key owned by an Admin or Super Admin.

SSW base URL, for example:

https://<your-ssw-host>

A free connector seat in your license. Creating a connector fails once the license limit is reached.

Tools

  • curl
  • jq (recommended)

Step 1: Get sdp_token

Request

SSW_HOST="<your-ssw-host>"
APIKEY="YOUR_API_KEY"

curl -s -X POST "https://${SSW_HOST}/iam/v1/apikey/authenticate" \
  -H "Content-Type: application/json" \
  -d "{\"apikey\":\"${APIKEY}\"}" \
  -o sdp_iam_token.json

Extract Token

SDP_TOKEN="$(jq -r '.data.sdp_token' sdp_iam_token.json)"
echo "$SDP_TOKEN"

Step 2: Pick an Edge and a Network

Pick an Edge

Each connector connects to one edge. Pick the edge closest to the network the connector will serve.

curl -s -X GET "https://${SSW_HOST}/ztna/v1/edge?connector_support=true&show_position=connector&page_size=10000" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" \
  -o edges.json

jq '.data.list[] | {edge_id, name, location}' edges.json

Example output:

{ "edge_id": "8fdfcf14-...", "name": "San Francisco, California", "location": "US" }
{ "edge_id": "5ec20361-...", "name": "Singapore, Singapore", "location": "SG" }

Choose one and save its edge_id:

EDGE_NAME="San Francisco, California"
EDGE_ID="$(jq -r --arg n "$EDGE_NAME" '.data.list[] | select(.name == $n) | .edge_id' edges.json)"
echo "EDGE_ID=$EDGE_ID"

⚠️ Important
The edge cannot be changed after the connector is created. To move a connector to another edge, delete it and create a new one.

Pick a Network

Every connector belongs to a network. Network names differ between organizations, so look yours up instead of assuming a name.

curl -s -X GET "https://${SSW_HOST}/ztna/v1/network?workspace_type=1" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" \
  -o networks.json

jq '.data.list[] | {network_id, name}' networks.json
NETWORK_NAME="$(jq -r '.data.list[0].name' networks.json)"   # or pick one by name
echo "NETWORK_NAME=$NETWORK_NAME"

Step 3: Create a Connector

Request Body

Field Type Required Description
name string Yes Connector name, unique within the organization, max 40 characters. Cannot be changed later.
display_name string No Name shown in the console. Defaults to name. Max 40 characters.
edge_id string Yes Edge from Step 2.
network_name string One of the two Network from Step 2.
network_id string One of the two Use instead of network_name.
allow_remote_control boolean Yes Set to true. A connector with false cannot be edited in the console.
conn_category integer No 0 = connector (default). This guide covers 0 only.
cluster_mode boolean No Run the connector as a cluster of instances. Cannot be turned off once enabled.
auto_bandwidth_detection boolean No Default false.
enable_shell boolean No Default false.
auto_upgrade boolean No Omit to follow the organization setting. true / false overrides it for this connector.
is_scan boolean No Enable network discovery scanning. Default false.
scan_targets string No Comma-separated IPs or CIDRs to scan.
scan_ports string No Comma-separated ports to scan.
scan_interval integer No Scan interval. Default 20.

Create Request

CONNECTOR_NAME="dev-qa-api-connector"

curl -s -X POST "https://${SSW_HOST}/ztna/v1/site" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" \
  -H "Content-Type: application/json" \
  --data "{
    \"name\": \"${CONNECTOR_NAME}\",
    \"display_name\": \"${CONNECTOR_NAME}\",
    \"edge_id\": \"${EDGE_ID}\",
    \"network_name\": \"${NETWORK_NAME}\",
    \"allow_remote_control\": true,
    \"conn_category\": 0,
    \"cluster_mode\": false,
    \"auto_bandwidth_detection\": false,
    \"enable_shell\": false,
    \"is_scan\": false,
    \"scan_interval\": 20
  }" \
  -o create_result.json

Validate Create Result

CREATE_CODE="$(jq -r '.code' create_result.json)"
if [ "$CREATE_CODE" != "0" ]; then
  echo "Create failed:"
  jq '{code, message}' create_result.json
  exit 1
fi

Extract site_id

SITE_ID="$(jq -r '.data.site_id' create_result.json)"
echo "SITE_ID=$SITE_ID"

Alternative: Look Up an Existing Connector

If the connector already exists, find its site_id by name:

curl -s -X GET "https://${SSW_HOST}/ztna/v1/site/all?workspace_type=0&conn_category=0" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" \
  -o connectors.json

SITE_ID="$(jq -r --arg n "$CONNECTOR_NAME" '.data.list[] | select(.name == $n) | .site_id' connectors.json)"
echo "SITE_ID=$SITE_ID"

Step 4: Get the Deploy Command

This returns ready-to-run commands that install the connector and register it with SSW. Run one of them on the host where the connector should run.

Deploy Command Request

curl -s -X GET "https://${SSW_HOST}/ztna/v1/connectorToken/${SITE_ID}/organization?type=All" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" \
  -o deploy.json

Response

{
  "code": 0,
  "data": {
    "name": "<deployment_name>",
    "token": "<deploy_token>",
    "all_token": {
      "docker": "docker pull ... && docker run ...",
      "helm": "helm repo add ... && helm install ...",
      "linux": "export SSW_CONNECTOR=... ",
      "desktop": "<deploy_token>",
      "darwin": "bash -c 'export SSW_CONNECTOR=... '",
      "windows": "$env:SSW_CONNECTOR_TOKEN=\"...\" ..."
    },
    "cli": {
      "linux": "bash -c 'arch=$(uname -m) && ... '",
      "darwin": "bash -c 'arch=$(uname -m) && ... '",
      "windows": "$CONNECTOR_DOWNLOAD_URL=\"...\" ..."
    }
  },
  "message": "Success"
}
Field Description
all_token.docker Run the connector as a Docker container
all_token.helm Install the connector into Kubernetes with Helm
all_token.linux Install on a Linux host
all_token.windows / all_token.darwin Install on Windows (PowerShell) / macOS
all_token.desktop The raw deploy token, for the desktop connector app
cli.* Command-line installers for Linux / macOS / Windows
token The raw deploy token, for building your own install command
name Service name used by the deployment. This is not the connector name.

Extract a Command (Example: Docker)

DEPLOY_CMD="$(jq -r '.data.all_token.docker' deploy.json)"
echo "$DEPLOY_CMD"

⚠️ Important

  • The deploy token expires after 24 hours. If you deploy later, call this API again to get a fresh command. This does not affect a connector that is already running.
  • The command contains a credential. Treat it like a secret and do not commit it to source control or share it in logs.
  • Do not call this API for the same connector in parallel. Concurrent calls are rejected with "Do not generate token so frequently".

Step 5: Update the Connector

The update API replaces the connector settings with the request body. It is not a partial update.

⚠️ Important
Sending only {"display_name": "new-name"} also sets allow_remote_control to false, turns off scanning, clears scan_targets / scan_ports, and sets scan_interval to 0.
Always read the current settings first, change what you need, and send the whole object back.

What Can Be Changed

Field Updatable Notes
display_name Yes Max 40 characters
network_id / network_name Yes Moves the connector to another network
allow_remote_control, auto_bandwidth_detection, enable_shell Yes
is_scan, scan_targets, scan_ports, scan_interval Yes
supported_functions Yes Send back the value of supported_functions_config from the GET response
cluster_mode false → true only Turning cluster mode off is rejected
auto_upgrade Yes Omit = keep the current setting; null = follow the organization setting; true / false = override
name, edge_id, conn_category No Fixed at creation

Read the Current Settings

curl -s -X GET "https://${SSW_HOST}/ztna/v1/site/${SITE_ID}" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" \
  -o connector.json

jq '.data | {name, display_name, network_id, allow_remote_control, enable_shell, is_scan, scan_targets, scan_ports, scan_interval, supported_functions_config}' connector.json

Build the Update Body

Copy the current settings, then change what you need. This example renames the connector and turns on shell access:

jq '.data | {
      name,
      display_name,
      network_id,
      allow_remote_control,
      auto_bandwidth_detection,
      enable_shell,
      cluster_mode,
      is_scan,
      scan_interval,
      scan_targets,
      scan_ports,
      supported_functions: .supported_functions_config
    }
    | .display_name = "dev-qa-api-connector-renamed"
    | .enable_shell = true' \
  connector.json > update_body.json

cat update_body.json

Send the Update

curl -s -X PUT "https://${SSW_HOST}/ztna/v1/site/${SITE_ID}" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" \
  -H "Content-Type: application/json" \
  --data @update_body.json \
  -o update_result.json

jq '{code, message}' update_result.json

Read the current settings again to confirm the change.

Step 6: Cleanup — Delete the Connector

⚠️ Important
Deleting a connector also deletes every application that uses it. List them before you delete.

List Applications Using the Connector

curl -s -X GET "https://${SSW_HOST}/ztna/v1/site/${SITE_ID}/app" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" | jq .data

Delete Request

curl -s -X DELETE "https://${SSW_HOST}/ztna/v1/site/${SITE_ID}" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer ${SDP_TOKEN}" \
  -o delete_result.json

jq '{code, message}' delete_result.json

Verify Deletion

After deletion, reading the connector returns 40001 Record not found:

curl -s -X GET "https://${SSW_HOST}/ztna/v1/site/${SITE_ID}" \
  -H "Authorization: Bearer ${SDP_TOKEN}" | jq '{code, message}'
{ "code": 40001, "message": "Record not found" }

Common Pitfalls

  • ❌ Using the API key directly to call /ztna/v1/... APIs
    → Always use sdp_token
  • ❌ Checking only the HTTP status
    → Business errors come back as HTTP 200 with a non-zero code (for example 40001 Record not found). Always check .code; 0 means success.
  • ❌ Getting a permission error on Step 4 with a Network Manager key
    → Getting the deploy command requires an Admin or Super Admin key
  • ❌ Sending only the changed fields to the update API
    → Omitted fields are reset, including allow_remote_control. Always read first and send the full object.
  • ❌ Hard-coding a network name such as Default
    → Network names differ per organization. Look them up in Step 2.
  • ❌ Running a deploy command that is more than 24 hours old
    → Call Step 4 again for a fresh command
  • ❌ Reusing a connector name
    → Names must be unique within the organization, including connectors created in the console
  • ❌ Deleting a connector that applications still use
    → Those applications are deleted too