--- title: "End-to-End Example: Create / Deploy / Update / Delete a Connector" slug: "end-to-end-example-create-deploy-update-delete-a-connector" updated: 2026-10-23T08:21:05Z published: 2026-10-23T08:21:05Z canonical: "docs.ssw.splashtop.com/end-to-end-example-create-deploy-update-delete-a-connector" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.ssw.splashtop.com/llms.txt > Use this file to discover all available pages before exploring further. # End-to-End Example: Create / Deploy / Update / Delete a Connector 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 > ``` > 💡 **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:// ``` **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="" 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": "", "token": "", "all_token": { "docker": "docker pull ... && docker run ...", "helm": "helm repo add ... && helm install ...", "linux": "export SSW_CONNECTOR=... ", "desktop": "", "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