{
	"info": {
		"_postman_id": "998e1e23-af08-47c6-8635-c776c757275f",
		"name": "vME",
		"description": "vME 1.10.0 REST API.\n\n**Setup**\n1. Set the `url` variable to your appliance's API address, including `/api`, for example `https://vme.example.com/api`.\n2. Run `user / login` with your username and password. Copy the `api-key` from the response into the `api-key` variable and your username into `username`. Every other request sends both as headers.\n3. Appliances use a self-signed certificate by default; turn off SSL certificate verification in Postman settings or install your own certificate on the appliance.\n\n**Folders**\n- **Onboarding (API)**: a whole onboarding workflow, run top to bottom, plus retry phases and clone-and-mount from an existing snapshot.\n- **Workflows**, **agents**, **objects**: list and remove workflows, enrollment tokens and agents, and delete several objects at once.\n- **Appliances (peer registry)**: register, test and trust the other vME appliances you send to.\n- The remaining folders cover pools, sources, snapshots, clones, containers, send and restore, users, LDAP and licences.\n\nRequests marked Admin only need an administrator's api-key. Full reference: https://docs.enov8.com/docs/vme/vme-api",
		"version": "1.10.0",
		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
		"_exporter_id": "23844346"
	},
	"protocolProfileBehavior": {
		"strictSSL": false
	},
	"item": [
		{
			"name": "Onboarding (API)",
			"description": "# vME Onboarding (API)\n\nDrive the **Onboard Application** flow end to end through the REST API: the same sequence the Onboard Application wizard runs, so you can follow it, run it live, or use Postman's **Code** button to copy each call into your own scripts.\n\nRun the requests top to bottom. Each one captures the values the next one needs into collection variables.\n\n## How a run is laid out\n- **One source per database.** A SQL Server source is a single dataset holding the whole database, so every stage (source, snapshot, send, clone) is one request.\n- **Mounted at a folder, not a drive letter.** Each host has a vME folder, set in its agent's tray Settings and reported by `DiscoverHost` as `defaults.vme_root`. A source is mounted at `<vME folder>\\sources\\<id>` and a clone at `<vME folder>\\clones\\<id>`, where the id is the dataset's guid. The agent jobs carry these as `mountRoot` and `mountId`.\n- **Scoped to whole target names.** The appliance names each iSCSI target itself. The jobs read that name back from `source/show` or `clone/show` and send it as `targets`, with `manualIQN` carrying the same value.\n\n## Before you start\n- **Two vME appliances** for the main flow: this one, where the database is ingested, and a target, where the clone is mounted. Register the target under **Appliances (peer registry) → Add an appliance**, which sets `peer_id`; the requests that act on the target go through this appliance with `POST /peer/{{peer_id}}/proxy`, so its api-key is not needed here.\n- **An enrolled iSCSI agent on each SQL host**, with a vME folder set in its tray Settings. The token requests here mint enrollment tokens; installing the agent on the Windows host is done on the host itself. Once an agent has enrolled, set `source_agent_id` / `target_agent_id` with the requests in the *Advanced* folder.\n- **Fill the collection variables** (Variables tab).\n\n## Variables\n- `url` - this appliance's base **including** `/api`, e.g. `https://source-vme/api`\n- `username` / `api-key` - this appliance's admin credentials\n- `source_portal` / `target_portal` - the iSCSI portal addresses of this appliance and of the target appliance (bare IPs, no scheme, no `/api`)\n- `pool_name` (this appliance's pool), `source_base` (the source's name), `snapshot_name`, `clone_base` (the clone's name)\n- `peer_id` - set by **Add an appliance**; `target_pool` - set by step 13\n- `target_host`, `target_username`, `target_api_key` - only for step 13b, which checks an appliance that is not registered\n- `template_id`, `workflow_id`, `job_id`, `snapshot_task_id`, `send_task_id`, `source_iqn`, `source_mount_id`, `source_mount_root`, `clone_iqn`, `clone_mount_id`, `target_mount_root` - set by the test scripts as you go\n\n## Notes\n- **Async**: agent jobs run in the background; poll `GET /agent-job?job_id=...`. A snapshot of a mounted source answers **202** with a task to poll at `GET /snapshot/task/<task_id>`. `db/send` answers with a `task_id`; poll `db/send/status` until `completed`.\n- **Agent job `config`** is the iSCSI connector's job config. See the iSCSI connector's API reference for every field.\n- **Ingest mode** (step 9): the `migrate` block takes one of three modes. Step 9's description has each one; *Advanced → SourceMigrateOnly* re-runs the ingest without formatting the volume again.\n- Edit the `YourDatabase` backup path in step 9 before running it.",
			"item": [
				{
					"name": "Main flow (run top-to-bottom)",
					"description": "The full onboarding: ingest a database on this appliance, snapshot it, send it to the target appliance, clone it there and mount it on the target SQL host. Run the requests top to bottom; each captures the values the next one needs. The two teardowns at the end, and their polls, are optional.",
					"item": [
						{
							"name": "1. List workflow templates",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/workflow-templates",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow-templates"
									]
								},
								"description": "Lists the workflow templates and sets `template_id` to the appliance's default, `sql_server_iscsi_one_volume`: SQL Server over iSCSI, one volume per database. A template that is switched off on this appliance cannot be used to create a workflow."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"if(j && j.default_template_id){pm.collectionVariables.set(\"template_id\",j.default_template_id);console.log(\"template_id =\",j.default_template_id)}"
										]
									}
								}
							]
						},
						{
							"name": "2. Create workflow",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"name\": \"Onboard {{source_base}}\",\n    \"workflow_type\": \"sql_host_clone\",\n    \"template_id\": \"{{template_id}}\",\n    \"source_mode\": \"iscsi_sql_host\",\n    \"target_mode\": \"different_vme\",\n    \"transport_mode\": \"vme_send\",\n    \"config\": {}\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Creates the workflow this flow drives. `parts` is left out, so all five parts run (ingest, snapshot, send, clone and mount): ten steps across two appliances. The response carries `parts` and `live_steps`, the steps this run has.\n\nSee *Clone and mount an existing snapshot* for a run that sets `parts` and `start_from`."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const w = j ? (j.workflow_id || (j.result&&(j.result.workflow_id||j.result.id)) || j.id) : null;",
											"if(w){pm.collectionVariables.set(\"workflow_id\",w);console.log(\"workflow_id =\",w);console.log(\"live_steps =\",((j.result||{}).live_steps||[]).join(\" · \"))}",
											"else{console.warn(\"workflow_id not found in response - set it manually from GET /workflow\")}"
										]
									}
								}
							]
						},
						{
							"name": "3. Create source (iSCSI)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/source/create",
									"host": [
										"{{url}}"
									],
									"path": [
										"source",
										"create"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"pool_name\": \"{{pool_name}}\",\n    \"name\": \"{{source_base}}\",\n    \"dbtype\": \"mssql\",\n    \"compression\": \"off\",\n    \"database_method\": \"network\",\n    \"network_info\": {\n        \"type\": \"iscsi\",\n        \"setting\": [\n            \"dedup=off\",\n            \"logbias=latency\",\n            \"sync=disabled\"\n        ],\n        \"auto_grow\": true,\n        \"auto_grow_max_gb\": 16384\n    },\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"source\",\n    \"role\": \"data\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Creates the source: one dataset holding the whole database, named `{{source_base}}`. `auto_grow` thin-provisions the volume, so it uses pool space only as data is written; send `vsize` (in GB) in place of the two `auto_grow` keys for a fixed size.\n\nThe source is created in the background. Wait until `GET {{url}}/source/status?pool_name={{pool_name}}&source_name={{source_base}}` reports it available before exporting it."
							}
						},
						{
							"name": "4. Export the source as an iSCSI target",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/db/network/create",
									"host": [
										"{{url}}"
									],
									"path": [
										"db",
										"network",
										"create"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"full_name\": \"{{pool_name}}/sources/{{source_base}}\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"source\",\n    \"role\": \"data\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Exports the source as an iSCSI target, so the SQL host can connect to it. An iSCSI export takes no `client_address`, `anonuid` or `anongid`: it listens on the appliance's iSCSI portal, on port 3260 of every interface. The appliance names the target itself; the next request reads that name back.\n\n`workflow_id`, `wizard_step` and `role` record the export on the workflow, which completes its Provision source step."
							}
						},
						{
							"name": "5. Read the source's target and id",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/source/show?pool_name={{pool_name}}&source_name={{source_base}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"source",
										"show"
									],
									"query": [
										{
											"key": "pool_name",
											"value": "{{pool_name}}"
										},
										{
											"key": "source_name",
											"value": "{{source_base}}"
										}
									]
								},
								"description": "Reads back the target name (`iqn_name`) and the dataset id (`guid`) the appliance recorded for the source, into `source_iqn` and `source_mount_id`. The host jobs below are scoped to that target, and the source is mounted in a folder named by that id."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const want = pm.collectionVariables.get(\"pool_name\") + \"/sources/\" + pm.collectionVariables.get(\"source_base\");",
											"const row = ((j && j.result) || []).find(r => r && r.name === want);",
											"if(row && row.iqn_name && row.guid){",
											"  pm.collectionVariables.set(\"source_iqn\", row.iqn_name);",
											"  pm.collectionVariables.set(\"source_mount_id\", row.guid);",
											"  console.log(\"source_iqn =\", row.iqn_name, \"| source_mount_id =\", row.guid)}",
											"else{console.warn(\"No target recorded for \" + want + \" yet. Send this again once its export has been created.\")}"
										]
									}
								}
							]
						},
						{
							"name": "6. Create enrollment token - source agent",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/agent-token",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-token"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"label\": \"{{source_base}}-source\",\n    \"environment\": \"source\",\n    \"ttl_minutes\": 60\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Mints a one-time token for installing the iSCSI agent on the source SQL host. Skip this if the agent is already enrolled. Once it has enrolled, run *Advanced → List source agents* to set `source_agent_id`."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"if(j&&j.result&&j.result.token){console.log(\"Install the agent on the SOURCE SQL host with this token (shown once):\",j.result.token)}",
											"console.warn(\"After the agent enrolls, set source_agent_id from GET /agent\")"
										]
									}
								}
							]
						},
						{
							"name": "7. Discover source host (agent job)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"agent_id\": \"{{source_agent_id}}\",\n    \"phase\": \"DiscoverHost\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"discover_prod\",\n    \"role\": \"source\",\n    \"job_type\": \"discovery\",\n    \"config\": {\n        \"portal\": \"{{source_portal}}\"\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Inventories the source SQL host: its SQL instances and databases, its disks, its iSCSI targets and sessions, and its vME folder. Giving `portal` refreshes that portal first, so a newly created target appears.\n\nEach database in the result carries its state alongside id, name, size and recovery model. Only a database reported ONLINE can be ingested."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "8. Poll discovery (source)",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job?job_id={{job_id}}&include_events=1",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									],
									"query": [
										{
											"key": "job_id",
											"value": "{{job_id}}"
										},
										{
											"key": "include_events",
											"value": "1"
										}
									]
								},
								"description": "Send again until the job is `completed`. Sets `source_mount_root` from the host's vME folder (`result.defaults.vme_root`), the folder the source is mounted under, written with its backslashes doubled so it can go straight into a JSON body. A host with no vME folder reports it empty: set the folder in the agent's tray Settings and discover the host again."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const job = j && j.result;",
											"if(!job){console.warn(\"No job in the response\")}",
											"else if(job.state!==\"completed\"){console.log(\"state =\", job.state, \"- send again until completed\")}",
											"else{const root = ((job.result||{}).defaults||{}).vme_root || \"\";",
											"  // Stored JSON-escaped, so a Windows path drops into a request body as valid JSON.",
											"  if(root){pm.collectionVariables.set(\"source_mount_root\", JSON.stringify(root).slice(1,-1));console.log(\"source_mount_root =\", root)}",
											"  else{console.warn(\"The host reported no vME folder. Set one in the agent's tray Settings, then discover the host again.\")}}"
										]
									}
								}
							]
						},
						{
							"name": "9. Source prep - mount and ingest (agent job)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"agent_id\": \"{{source_agent_id}}\",\n    \"phase\": \"SourcePrep\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"source_prep\",\n    \"role\": \"source\",\n    \"job_type\": \"iscsi_workflow\",\n    \"config\": {\n        \"portal\": \"{{source_portal}}\",\n        \"clearOldPortals\": false,\n        \"manualIQN\": \"{{source_iqn}}\",\n        \"targets\": [\n            \"{{source_iqn}}\"\n        ],\n        \"targetSelection\": \"ALL\",\n        \"confirmPrep\": true,\n        \"mountRoot\": \"{{source_mount_root}}\",\n        \"mountId\": \"{{source_mount_id}}\",\n        \"migrate\": {\n            \"confirmStart\": true,\n            \"confirmSelection\": true,\n            \"execute\": true,\n            \"dbPrefix\": \"ISCSI_\",\n            \"dbIds\": \"ALL\",\n            \"backupPaths\": [\n                \"C:\\\\backups\\\\YourDatabase.bak\"\n            ]\n        },\n        \"job_timeout_seconds\": 86400\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Connects the source's target, formats the volume and mounts it at `<source_mount_root>\\sources\\<source_mount_id>`, then loads the database onto it through the `migrate` block. No drive letter is used.\n\n`targets` names the whole target, and `manualIQN` carries the same name.\n\n**Ingest mode - pick ONE.** Set only that mode's fields inside `migrate`. Windows paths use double backslashes because the body is JSON.\n\n- **Back up and restore a database attached on this host:** `\"dbIds\": \"5,6\"` (ids from discovery), or `\"dbNameFilter\": \"YourDatabase\"`.\n- **Restore from existing .bak files** (shown in this request's body): `\"dbIds\": \"ALL\", \"backupPaths\": [\"C:\\\\backups\\\\YourDatabase.bak\"]`.\n- **Copy loose .mdf/.ldf files:** `\"sourcePaths\": { \"dataPath\": \"D:\\\\Data\", \"logPath\": \"L:\\\\Logs\" }`.\n\n`migrate.dbPrefix` is the prefix the ingested databases are given. `migrate.sqlInstance` pins the SQL instance the ingest connects to (for example `.\\\\TDM_STAGING`); leave it out and the connector picks the default instance when installed, otherwise the first named one. When you pick databases by id, also send `migrate.selectionInstance`, the instance discovery reported them on, so the job stops if it resolves to a different one.\n\n`execute: false` runs the ingest as a dry run. `config.job_timeout_seconds` sets the job's timeout (default 86400 seconds; 60 to 604800 accepted)."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "10. Poll agent job (Source prep)",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job?job_id={{job_id}}&include_events=1",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									],
									"query": [
										{
											"key": "job_id",
											"value": "{{job_id}}"
										},
										{
											"key": "include_events",
											"value": "1"
										}
									]
								},
								"description": "Send again until the Source prep job reaches a final state before snapshotting: it formats the volume and loads the database, so a snapshot taken earlier captures an empty volume."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const job = j && j.result;",
											"if(job){console.log(\"state =\", job.state, \"|\", job.message||\"\")}"
										]
									}
								}
							]
						},
						{
							"name": "11. Snapshot source",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/snapshot/create",
									"host": [
										"{{url}}"
									],
									"path": [
										"snapshot",
										"create"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"pool_name\": \"{{pool_name}}\",\n    \"source_name\": \"{{source_base}}\",\n    \"name\": \"{{snapshot_name}}\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"snapshot\",\n    \"role\": \"data\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Snapshots the source. The source is mounted on the source host, so the snapshot is taken through that host: the call answers **202** with a `task_id` (set into `snapshot_task_id`), and the appliance takes the databases on the volume offline, snapshots it, and brings them back online. Follow it with the next request.\n\nIf the host cannot be told (its agent is offline, or another coordinated operation is running on it), the call answers **409** with the reason and the snapshot is not taken. Send `\"skip_host\": true` only if you have already taken those databases offline yourself."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"if(j && j.task_id){pm.collectionVariables.set(\"snapshot_task_id\", j.task_id);console.log(\"snapshot_task_id =\", j.task_id)}",
											"else if(pm.response.code===409){console.warn(\"Not taken:\", j && j.message)}",
											"else{console.log(\"Snapshot taken directly:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "12. Poll snapshot task",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/snapshot/task/{{snapshot_task_id}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"snapshot",
										"task",
										"{{snapshot_task_id}}"
									]
								},
								"description": "Send again until `state` is `SUCCESS` (or `FAILURE`). `steps` reports each part as the host does it: taking the databases offline, the snapshot, and bringing them back online."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"if(j){console.log(\"state =\", j.state);(j.steps||[]).forEach(s=>console.log(\" -\", s.label||s.name||s.key, \":\", s.state||s.status))}"
										]
									}
								}
							]
						},
						{
							"name": "13. Validate target appliance",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow/{{workflow_id}}/remote-preview",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow",
										"{{workflow_id}}",
										"remote-preview"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"peer_id\": \"{{peer_id}}\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Confirms the registered target appliance is reachable, lists its pools (setting `target_pool` to the first) and pushes SSH trust to it. Its address, admin username and api-key are read from the appliance registry. Run **Appliances (peer registry) → Add an appliance** first to set `peer_id`."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"if(j&&j.result&&j.result.pools){console.log(\"Target pools:\",JSON.stringify(j.result.pools));if(j.result.pools.length){pm.collectionVariables.set(\"target_pool\",(j.result.pools[0]&&j.result.pools[0].name)||j.result.pools[0])}}"
										]
									}
								}
							]
						},
						{
							"name": "13b. Validate target by address and api-key",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow/{{workflow_id}}/remote-preview",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow",
										"{{workflow_id}}",
										"remote-preview"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"address\": \"{{target_host}}\",\n    \"admin_username\": \"{{target_username}}\",\n    \"admin_api_key\": \"{{target_api_key}}\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "The same check for an appliance that is not registered, addressed by its URL and an administrator api-key on it. The requests after this one reach the target through the registry, so register it before carrying on."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"if(j&&j.result&&j.result.pools){console.log(\"Target pools:\",JSON.stringify(j.result.pools));if(j.result.pools.length){pm.collectionVariables.set(\"target_pool\",(j.result.pools[0]&&j.result.pools[0].name)||j.result.pools[0])}}"
										]
									}
								}
							]
						},
						{
							"name": "14. Send to target",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/db/send",
									"host": [
										"{{url}}"
									],
									"path": [
										"db",
										"send"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"type\": \"sys2sys\",\n    \"dataset\": \"{{pool_name}}/sources/{{source_base}}@{{snapshot_name}}\",\n    \"receiver\": {\n        \"peer_id\": \"{{peer_id}}\",\n        \"pool_name\": \"{{target_pool}}\",\n        \"dataset_name\": \"{{source_base}}\"\n    },\n    \"overwrite\": false,\n    \"keep_snapshot\": false,\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"send\",\n    \"role\": \"data\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Replicates the snapshot to the registered target appliance, as a source named `{{source_base}}` in `target_pool`. `receiver.peer_id` names the appliance; its address and credentials are read from the registry. Answers **202** with a `task_id` (set into `send_task_id`).\n\n`overwrite: true` replaces a source of the same name on the target, and is refused if that source has clones there. `keep_snapshot: true` keeps the snapshot the send takes for itself on this appliance."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"if(j&&j.task_id){pm.collectionVariables.set(\"send_task_id\",j.task_id);console.log(\"send_task_id =\",j.task_id)}"
										]
									}
								}
							]
						},
						{
							"name": "15. Poll send status",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/db/send/status?task_id={{send_task_id}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"db",
										"send",
										"status"
									],
									"query": [
										{
											"key": "task_id",
											"value": "{{send_task_id}}"
										}
									]
								},
								"description": "Send again until the transfer reports `completed`."
							}
						},
						{
							"name": "16. Create clone on target",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"POST\",\n    \"path\": \"/clone/create\",\n    \"body\": {\n        \"pool_name\": \"{{target_pool}}\",\n        \"source_name\": \"{{target_pool}}/sources/{{source_base}}\",\n        \"snapshot_name\": \"{{snapshot_name}}\",\n        \"name\": \"{{clone_base}}\",\n        \"dbtype\": \"mssql\",\n        \"database_method\": \"network\",\n        \"network_info\": {\n            \"type\": \"iscsi\"\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Creates a writable clone, `{{clone_base}}`, from the snapshot the target received, and exports it as an iSCSI target there.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							}
						},
						{
							"name": "17. Read the clone's target and id",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"GET\",\n    \"path\": \"/clone/show?pool_name={{target_pool}}\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Reads back the target name (`iqn_name`) and the dataset id (`guid`) the target appliance recorded for the clone, into `clone_iqn` and `clone_mount_id`. Send again if the export has not been created yet.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const want = pm.collectionVariables.get(\"target_pool\") + \"/clones/\" + pm.collectionVariables.get(\"clone_base\");",
											"const row = ((j && j.result) || []).find(r => r && r.name === want);",
											"if(row && row.iqn_name && row.guid){",
											"  pm.collectionVariables.set(\"clone_iqn\", row.iqn_name);",
											"  pm.collectionVariables.set(\"clone_mount_id\", row.guid);",
											"  console.log(\"clone_iqn =\", row.iqn_name, \"| clone_mount_id =\", row.guid)}",
											"else{console.warn(\"No target recorded for \" + want + \" yet. Send this again once its export has been created.\")}"
										]
									}
								}
							]
						},
						{
							"name": "18. Record the clone on the workflow",
							"request": {
								"method": "PATCH",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow/{{workflow_id}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow",
										"{{workflow_id}}"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"config\": {\n        \"clone\": {\n            \"completed\": true,\n            \"pool_name\": \"{{target_pool}}\",\n            \"clone_name\": \"{{clone_base}}\",\n            \"data\": {\n                \"name\": \"{{clone_base}}\",\n                \"full_name\": \"{{target_pool}}/clones/{{clone_base}}\",\n                \"source_name\": \"{{target_pool}}/sources/{{source_base}}\",\n                \"snapshot_name\": \"{{target_pool}}/sources/{{source_base}}@{{snapshot_name}}\"\n            }\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "The clone was made on the target appliance, so this appliance records it on the workflow here. This completes the Create clone step, and lets a later delete of the workflow offer to destroy the clone."
							}
						},
						{
							"name": "19. Create enrollment token - target agent",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"POST\",\n    \"path\": \"/agent-token\",\n    \"body\": {\n        \"label\": \"{{source_base}}-target\",\n        \"environment\": \"target\",\n        \"ttl_minutes\": 60\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Mints a one-time token for installing the iSCSI agent on the target SQL host, enrolled with the target appliance. Skip this if the agent is already enrolled. Once it has enrolled, run *Advanced → List target agents* to set `target_agent_id`.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"if(j&&j.result&&j.result.token){console.log(\"Install the agent on the TARGET SQL host with this token (shown once):\",j.result.token)}",
											"console.warn(\"After the agent enrolls, set target_agent_id (Advanced -> List target agents)\")"
										]
									}
								}
							]
						},
						{
							"name": "20. Discover target host (agent job)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"POST\",\n    \"path\": \"/agent-job\",\n    \"body\": {\n        \"agent_id\": \"{{target_agent_id}}\",\n        \"phase\": \"DiscoverHost\",\n        \"workflow_id\": \"{{workflow_id}}\",\n        \"wizard_step\": \"discover_nonprod\",\n        \"role\": \"clone\",\n        \"job_type\": \"discovery\",\n        \"config\": {\n            \"portal\": \"{{target_portal}}\"\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Inventories the target SQL host, including its vME folder. `portal` is the target appliance's iSCSI portal address.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "21. Poll discovery (target)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"GET\",\n    \"path\": \"/agent-job?job_id={{job_id}}&include_events=1\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Send again until the job is `completed`. Sets `target_mount_root` from the host's vME folder, the folder the clone is mounted under.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const job = j && j.result;",
											"if(!job){console.warn(\"No job in the response\")}",
											"else if(job.state!==\"completed\"){console.log(\"state =\", job.state, \"- send again until completed\")}",
											"else{const root = ((job.result||{}).defaults||{}).vme_root || \"\";",
											"  // Stored JSON-escaped, so a Windows path drops into a request body as valid JSON.",
											"  if(root){pm.collectionVariables.set(\"target_mount_root\", JSON.stringify(root).slice(1,-1));console.log(\"target_mount_root =\", root)}",
											"  else{console.warn(\"The host reported no vME folder. Set one in the agent's tray Settings, then discover the host again.\")}}"
										]
									}
								}
							]
						},
						{
							"name": "22. Mount + attach clone (agent job, target)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"POST\",\n    \"path\": \"/agent-job\",\n    \"body\": {\n        \"agent_id\": \"{{target_agent_id}}\",\n        \"phase\": \"CloneMount\",\n        \"workflow_id\": \"{{workflow_id}}\",\n        \"wizard_step\": \"clone_mount\",\n        \"role\": \"clone\",\n        \"job_type\": \"iscsi_workflow\",\n        \"config\": {\n            \"portal\": \"{{target_portal}}\",\n            \"manualIQN\": \"{{clone_iqn}}\",\n            \"targets\": [\n                \"{{clone_iqn}}\"\n            ],\n            \"dataset\": \"{{target_pool}}/clones/{{clone_base}}\",\n            \"targetSelection\": \"ALL\",\n            \"mountRoot\": \"{{target_mount_root}}\",\n            \"mountId\": \"{{clone_mount_id}}\",\n            \"attach\": {\n                \"sqlInstance\": \"localhost\",\n                \"skipPartitionAssign\": true,\n                \"autoPair\": true,\n                \"dbSelection\": \"ALL\",\n                \"dbPrefix\": \"ISCSI_\"\n            }\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Connects the clone's target on the target SQL host, mounts the volume at `<target_mount_root>\\clones\\<clone_mount_id>`, and attaches the databases it finds. No drive letter is used.\n\n`targets` names the whole target, and `manualIQN` carries the same name. `attach.dbSelection` is `ALL`, or a comma-separated list of the databases on the clone. `attach.dbPrefix` should be the prefix the ingest used: it is applied only when a database's name does not already start with it, so the clone attaches under the name the ingest created.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "23. Poll mount job (target)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"GET\",\n    \"path\": \"/agent-job?job_id={{job_id}}&include_events=1\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Send again until the mount job reaches a final state.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const job = j && j.result;",
											"if(job){console.log(\"state =\", job.state, \"|\", job.message||\"\")}"
										]
									}
								}
							]
						},
						{
							"name": "24. Record the mount on the workflow",
							"request": {
								"method": "PATCH",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow/{{workflow_id}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow",
										"{{workflow_id}}"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"config\": {\n        \"clone_mount\": {\n            \"job_id\": \"{{job_id}}\",\n            \"job_state\": \"completed\",\n            \"completed\": true,\n            \"portal\": \"{{target_portal}}\",\n            \"manualIQN\": \"{{clone_iqn}}\",\n            \"sqlInstance\": \"localhost\",\n            \"targetSelection\": \"ALL\",\n            \"dbSelection\": \"ALL\",\n            \"mountRoot\": \"{{target_mount_root}}\",\n            \"mountId\": \"{{clone_mount_id}}\"\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "The mount job ran on the target appliance, so its outcome is recorded on the workflow here: this completes the Mount + attach clone step. Set `job_state` to the state the job finished in, and `completed` to `false` if it did not complete. The mount's folder is recorded with it, so the clone can be torn down from the wizard later."
							}
						},
						{
							"name": "25. Mark the workflow complete",
							"request": {
								"method": "PATCH",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow/{{workflow_id}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow",
										"{{workflow_id}}"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"state\": \"completed\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Refused with **409** while the recorded mount job is unfinished, or after a step has failed; pass `\"force\": true` to override."
							}
						},
						{
							"name": "26. Tear down clone - detach + disconnect (optional, target)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"POST\",\n    \"path\": \"/agent-job\",\n    \"body\": {\n        \"agent_id\": \"{{target_agent_id}}\",\n        \"phase\": \"CloneUnmount\",\n        \"workflow_id\": \"{{workflow_id}}\",\n        \"wizard_step\": \"complete\",\n        \"role\": \"clone\",\n        \"job_type\": \"iscsi_workflow\",\n        \"config\": {\n            \"portal\": \"{{target_portal}}\",\n            \"manualIQN\": \"{{clone_iqn}}\",\n            \"targets\": [\n                \"{{clone_iqn}}\"\n            ],\n            \"dataset\": \"{{target_pool}}/clones/{{clone_base}}\",\n            \"mountRoot\": \"{{target_mount_root}}\",\n            \"mountId\": \"{{clone_mount_id}}\",\n            \"unmount\": {\n                \"sqlInstance\": \"localhost\",\n                \"dbSelection\": \"MATCH\",\n                \"disconnectTargets\": \"MATCH\",\n                \"fullCleanup\": false,\n                \"dbPrefix\": \"ISCSI_\"\n            }\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Optional. Detaches the clone's databases on the target SQL host, releases its folder and disconnects its iSCSI session. The clone dataset on the appliance is untouched.\n\n`dbSelection` and `disconnectTargets` set to `MATCH` scope the work to the target named by `manualIQN`; `mountRoot` and `mountId` scope the detach to the clone's folder, which is removed once its disk is gone. Keep `fullCleanup: false`: `true` disconnects every iSCSI session on the host and clears its initiator configuration. `unmount.dbPrefix` must match the names the databases were attached under.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "27. Poll teardown (target)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/proxy",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"proxy"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"method\": \"GET\",\n    \"path\": \"/agent-job?job_id={{job_id}}&include_events=1\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Send again until the teardown job reaches a final state.\n\nSent through this appliance with `POST /peer/{{peer_id}}/proxy`, which carries the call to the registered target appliance with the credentials stored for it and returns its answer unchanged."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const job = j && j.result;",
											"if(job){console.log(\"state =\", job.state, \"|\", job.message||\"\")}"
										]
									}
								}
							]
						},
						{
							"name": "28. Tear down source - detach staging databases (optional, source)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"agent_id\": \"{{source_agent_id}}\",\n    \"phase\": \"CloneUnmount\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"complete\",\n    \"role\": \"source\",\n    \"job_type\": \"iscsi_workflow\",\n    \"config\": {\n        \"portal\": \"{{source_portal}}\",\n        \"manualIQN\": \"{{source_iqn}}\",\n        \"targets\": [\n            \"{{source_iqn}}\"\n        ],\n        \"dataset\": \"{{pool_name}}/sources/{{source_base}}\",\n        \"mountRoot\": \"{{source_mount_root}}\",\n        \"mountId\": \"{{source_mount_id}}\",\n        \"unmount\": {\n            \"dbSelection\": \"MATCH\",\n            \"disconnectTargets\": \"MATCH\",\n            \"fullCleanup\": false,\n            \"dbPrefix\": \"ISCSI_\"\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Optional. Detaches the ingested databases on the source SQL host, releases the source's folder and disconnects its iSCSI session, scoped to the source's target and folder as in the clone teardown. The source dataset on the appliance is untouched, so it can still be snapshotted and cloned. `unmount.sqlInstance` is left out, so the connector detects the instance; send it if the ingest was pinned to one."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "29. Poll teardown (source)",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job?job_id={{job_id}}&include_events=1",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									],
									"query": [
										{
											"key": "job_id",
											"value": "{{job_id}}"
										},
										{
											"key": "include_events",
											"value": "1"
										}
									]
								},
								"description": "Send again until the teardown job reaches a final state."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const job = j && j.result;",
											"if(job){console.log(\"state =\", job.state, \"|\", job.message||\"\")}"
										]
									}
								}
							]
						}
					]
				},
				{
					"name": "Advanced / retry phases (run individually)",
					"description": "Helpers and alternatives to the main flow, run one at a time, not as part of a top-to-bottom run. SourcePrep (main-flow step 9) is SourcePrepOnly followed by SourceMigrateOnly; run those two in place of step 9 to retry one half, for example to re-ingest after a failed load. Do not include this folder in a full Collection Run.",
					"item": [
						{
							"name": "List source agents (set source_agent_id)",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/agent?environment=source",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent"
									],
									"query": [
										{
											"key": "environment",
											"value": "source"
										}
									]
								},
								"description": "Lists the agents enrolled on this appliance with environment `source`, and sets `source_agent_id` to the first. Run it once the agent has enrolled on the source SQL host. Every agent found is logged to the console; if more than one matches, copy the right `agent_id` into `source_agent_id`."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const arr = j && Array.isArray(j.result) ? j.result : [];",
											"arr.forEach(a=>console.log('agent:', a.agent_id, '|', a.label||a.host_name, '|', a.status));",
											"const a = arr[0];",
											"if(a && a.agent_id){pm.collectionVariables.set(\"source_agent_id\", a.agent_id);console.log(\"source_agent_id =\", a.agent_id);}",
											"else{console.warn(\"No source agent found - enroll one first (token step), then re-run; or set source_agent_id manually\");}"
										]
									}
								}
							]
						},
						{
							"name": "List target agents (set target_agent_id)",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/peer/{{peer_id}}/agents",
									"host": [
										"{{url}}"
									],
									"path": [
										"peer",
										"{{peer_id}}",
										"agents"
									]
								},
								"description": "Lists the agents enrolled on the registered target appliance, read with the credentials stored for it, and sets `target_agent_id` to the first agent with environment `target` (else the first listed). Every agent found is logged to the console; if the wrong one was picked, copy the right `agent_id` into `target_agent_id`."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const arr = j && Array.isArray(j.result) ? j.result : [];",
											"arr.forEach(a=>console.log('agent:', a.agent_id, '|', a.label||a.host_name, '|', a.environment, '|', a.status));",
											"const a = arr.find(x => x.environment === \"target\") || arr[0];",
											"if(a && a.agent_id){pm.collectionVariables.set(\"target_agent_id\", a.agent_id);console.log(\"target_agent_id =\", a.agent_id);}",
											"else{console.warn(\"No target agent found - enroll one first (token step), then re-run; or set target_agent_id manually\");}"
										]
									}
								}
							]
						},
						{
							"name": "SourcePrepOnly - prepare the volume (retry)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"agent_id\": \"{{source_agent_id}}\",\n    \"phase\": \"SourcePrepOnly\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"source_prep\",\n    \"role\": \"source\",\n    \"job_type\": \"iscsi_workflow\",\n    \"config\": {\n        \"portal\": \"{{source_portal}}\",\n        \"clearOldPortals\": false,\n        \"manualIQN\": \"{{source_iqn}}\",\n        \"targets\": [\n            \"{{source_iqn}}\"\n        ],\n        \"targetSelection\": \"ALL\",\n        \"confirmPrep\": true,\n        \"mountRoot\": \"{{source_mount_root}}\",\n        \"mountId\": \"{{source_mount_id}}\"\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Connects the source's target, formats the volume and mounts it at its folder, without loading any data: the first half of main-flow step 9. Run SourcePrepOnly and then SourceMigrateOnly in place of step 9, not as well as it. Poll with `GET {{url}}/agent-job?job_id={{job_id}}`.\n\nThis formats the volume. Run it only on a new, empty source."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "SourceMigrateOnly - ingest only (retry)",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"agent_id\": \"{{source_agent_id}}\",\n    \"phase\": \"SourceMigrateOnly\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"source_prep\",\n    \"role\": \"source\",\n    \"job_type\": \"iscsi_workflow\",\n    \"config\": {\n        \"portal\": \"{{source_portal}}\",\n        \"clearOldPortals\": false,\n        \"manualIQN\": \"{{source_iqn}}\",\n        \"targets\": [\n            \"{{source_iqn}}\"\n        ],\n        \"targetSelection\": \"ALL\",\n        \"confirmPrep\": true,\n        \"mountRoot\": \"{{source_mount_root}}\",\n        \"mountId\": \"{{source_mount_id}}\",\n        \"migrate\": {\n            \"confirmStart\": true,\n            \"confirmSelection\": true,\n            \"execute\": true,\n            \"dbPrefix\": \"ISCSI_\",\n            \"dbIds\": \"ALL\",\n            \"backupPaths\": [\n                \"C:\\\\backups\\\\YourDatabase.bak\"\n            ]\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Loads the database onto a source volume that is already prepared and mounted at its folder (by step 9 or by SourcePrepOnly), without formatting it again. Use it to retry a failed ingest. The same three ingest modes as step 9 apply - pick ONE: database ids or `dbNameFilter` (back up and restore), `backupPaths` (restore from .bak, shown here), or `sourcePaths` (copy loose files). Poll with `GET {{url}}/agent-job?job_id={{job_id}}`.\n\n`migrate.sqlInstance` behaves as in step 9: left out, the connector detects the instance."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						}
					]
				},
				{
					"name": "Clone and mount an existing snapshot",
					"description": "The short run: clone a snapshot you already have on this appliance and mount it on a host, with no ingest and no transfer. Seven wizard steps, and repeatable for one host after another.\n\nSet `pool_name`, `source_base`, `clone_base`, `target_agent_id` and `target_portal` first, then run top to bottom.",
					"item": [
						{
							"name": "1. Find the source to start from",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/source/show?pool_name={{pool_name}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"source",
										"show"
									],
									"query": [
										{
											"key": "pool_name",
											"value": "{{pool_name}}"
										}
									]
								},
								"description": "Lists the sources in `pool_name`. A SQL Server source is one dataset per database. Set `source_base` to the name of the one you want to clone; if it is already set, its target name and id are read into `source_iqn` and `source_mount_id`."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const want = pm.collectionVariables.get(\"pool_name\") + \"/sources/\" + pm.collectionVariables.get(\"source_base\");",
											"const row = ((j && j.result) || []).find(r => r && r.name === want);",
											"if(row && row.iqn_name && row.guid){",
											"  pm.collectionVariables.set(\"source_iqn\", row.iqn_name);",
											"  pm.collectionVariables.set(\"source_mount_id\", row.guid);",
											"  console.log(\"source_iqn =\", row.iqn_name, \"| source_mount_id =\", row.guid)}",
											"else{console.warn(\"No target recorded for \" + want + \" yet. Send this again once its export has been created.\")}"
										]
									}
								}
							]
						},
						{
							"name": "2. Find the snapshot to start from",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/snapshot/show?pool_name={{pool_name}}&source_name={{source_base}}&sort=true",
									"host": [
										"{{url}}"
									],
									"path": [
										"snapshot",
										"show"
									],
									"query": [
										{
											"key": "pool_name",
											"value": "{{pool_name}}"
										},
										{
											"key": "source_name",
											"value": "{{source_base}}"
										},
										{
											"key": "sort",
											"value": "true"
										}
									]
								},
								"description": "Lists the source's snapshots and sets `snapshot_name` to the newest. Set it yourself to use another one."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const names = (j && j.snapshot_names) || [];",
											"if(names.length){const leaf = String(names[names.length-1]).split(\"@\")[1];",
											"  if(leaf){pm.collectionVariables.set(\"snapshot_name\", leaf);  console.log(\"snapshot_name =\", leaf)}}"
										]
									}
								}
							]
						},
						{
							"name": "3. Create a clone-and-mount workflow",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"name\": \"Clone {{source_base}} as {{clone_base}}\",\n    \"workflow_type\": \"same_vme_clone_restore\",\n    \"template_id\": \"{{template_id}}\",\n    \"source_mode\": \"iscsi_sql_host\",\n    \"target_mode\": \"same_vme\",\n    \"transport_mode\": \"local_clone\",\n    \"parts\": [\n        \"clone\",\n        \"mount\"\n    ],\n    \"start_from\": {\n        \"source\": {\n            \"pool_name\": \"{{pool_name}}\",\n            \"source_name\": \"{{source_base}}\",\n            \"full_name\": \"{{pool_name}}/sources/{{source_base}}\",\n            \"data_full_name\": \"{{pool_name}}/sources/{{source_base}}\",\n            \"data\": {\n                \"name\": \"{{source_base}}\",\n                \"full_name\": \"{{pool_name}}/sources/{{source_base}}\",\n                \"role\": \"data\",\n                \"iqn_name\": \"{{source_iqn}}\"\n            },\n            \"data_completed\": true,\n            \"picked\": true,\n            \"completed\": true\n        },\n        \"snapshot\": {\n            \"snapshot_name\": \"{{snapshot_name}}\",\n            \"data\": {\n                \"name\": \"{{snapshot_name}}\",\n                \"source_name\": \"{{source_base}}\",\n                \"source_full_name\": \"{{pool_name}}/sources/{{source_base}}\",\n                \"full_snapshot_name\": \"{{pool_name}}/sources/{{source_base}}@{{snapshot_name}}\"\n            },\n            \"picked\": true,\n            \"completed\": true\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "`parts` is which of **ingest · snapshot · send · clone · mount** this run does; a part left out is off. Leave `parts` out entirely and all five run.\n\nA part that is off has to get its input from somewhere, so `start_from` carries the source and the snapshot the run begins from. With no `send` part the clone is made on this appliance. The response's `live_steps` is the list of steps this run has - here `basics · pick_source · pick_snapshot · clone · nonprod_agent · discover_nonprod · clone_mount · complete`.\n\nRefused with **400** if the combination cannot run: nothing selected, `mount` without `clone`, or `clone`/`send` with no snapshot while `ingest` is on."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const w = j && j.result;",
											"if(w&&w.workflow_id){pm.collectionVariables.set(\"workflow_id\",w.workflow_id);",
											"  console.log(\"workflow_id =\",w.workflow_id);",
											"  console.log(\"parts       =\",JSON.stringify(w.parts));",
											"  console.log(\"live_steps  =\",(w.live_steps||[]).join(\" · \"))}",
											"else{console.warn(\"workflow_id not in response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "4. Move to the clone step",
							"request": {
								"method": "PATCH",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow/{{workflow_id}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow",
										"{{workflow_id}}"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"current_step\": \"clone\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "`current_step` is checked against the steps this run has: a step whose part is off is refused with **400** naming the steps it does have (`force: true` overrides). As the run moves on, its `state` skips any state whose part is off, so this run never reports itself as `source_provisioning`."
							}
						},
						{
							"name": "5. Create the clone",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/clone/create",
									"host": [
										"{{url}}"
									],
									"path": [
										"clone",
										"create"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"pool_name\": \"{{pool_name}}\",\n    \"source_name\": \"{{pool_name}}/sources/{{source_base}}\",\n    \"snapshot_name\": \"{{snapshot_name}}\",\n    \"name\": \"{{clone_base}}\",\n    \"dbtype\": \"mssql\",\n    \"database_method\": \"network\",\n    \"network_info\": {\n        \"type\": \"iscsi\"\n    },\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"clone\",\n    \"role\": \"data\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Creates a writable clone, `{{clone_base}}`, from the snapshot, on this appliance, and exports it as an iSCSI target. `workflow_id`, `wizard_step` and `role` record it on the workflow, which completes the Create clone step."
							}
						},
						{
							"name": "6. Read the clone's target and id",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/clone/show?pool_name={{pool_name}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"clone",
										"show"
									],
									"query": [
										{
											"key": "pool_name",
											"value": "{{pool_name}}"
										}
									]
								},
								"description": "Reads back the target name (`iqn_name`) and the dataset id (`guid`) recorded for the clone, into `clone_iqn` and `clone_mount_id`. Send again if the export has not been created yet."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const want = pm.collectionVariables.get(\"pool_name\") + \"/clones/\" + pm.collectionVariables.get(\"clone_base\");",
											"const row = ((j && j.result) || []).find(r => r && r.name === want);",
											"if(row && row.iqn_name && row.guid){",
											"  pm.collectionVariables.set(\"clone_iqn\", row.iqn_name);",
											"  pm.collectionVariables.set(\"clone_mount_id\", row.guid);",
											"  console.log(\"clone_iqn =\", row.iqn_name, \"| clone_mount_id =\", row.guid)}",
											"else{console.warn(\"No target recorded for \" + want + \" yet. Send this again once its export has been created.\")}"
										]
									}
								}
							]
						},
						{
							"name": "7. Discover the host that will mount it",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"agent_id\": \"{{target_agent_id}}\",\n    \"phase\": \"DiscoverHost\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"discover_nonprod\",\n    \"role\": \"clone\",\n    \"job_type\": \"discovery\",\n    \"config\": {\n        \"portal\": \"{{target_portal}}\"\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "With no `send` part the clone stays on this appliance, so `target_portal` is **this** appliance's iSCSI portal address and the agent is one enrolled here."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "8. Poll discovery",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job?job_id={{job_id}}&include_events=1",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									],
									"query": [
										{
											"key": "job_id",
											"value": "{{job_id}}"
										},
										{
											"key": "include_events",
											"value": "1"
										}
									]
								},
								"description": "Send again until the job is `completed`. Sets `target_mount_root` from the host's vME folder, the folder the clone is mounted under."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const job = j && j.result;",
											"if(!job){console.warn(\"No job in the response\")}",
											"else if(job.state!==\"completed\"){console.log(\"state =\", job.state, \"- send again until completed\")}",
											"else{const root = ((job.result||{}).defaults||{}).vme_root || \"\";",
											"  // Stored JSON-escaped, so a Windows path drops into a request body as valid JSON.",
											"  if(root){pm.collectionVariables.set(\"target_mount_root\", JSON.stringify(root).slice(1,-1));console.log(\"target_mount_root =\", root)}",
											"  else{console.warn(\"The host reported no vME folder. Set one in the agent's tray Settings, then discover the host again.\")}}"
										]
									}
								}
							]
						},
						{
							"name": "9. Mount and attach the clone",
							"request": {
								"method": "POST",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"agent_id\": \"{{target_agent_id}}\",\n    \"phase\": \"CloneMount\",\n    \"workflow_id\": \"{{workflow_id}}\",\n    \"wizard_step\": \"clone_mount\",\n    \"role\": \"clone\",\n    \"job_type\": \"iscsi_workflow\",\n    \"config\": {\n        \"portal\": \"{{target_portal}}\",\n        \"manualIQN\": \"{{clone_iqn}}\",\n        \"targets\": [\n            \"{{clone_iqn}}\"\n        ],\n        \"dataset\": \"{{pool_name}}/clones/{{clone_base}}\",\n        \"targetSelection\": \"ALL\",\n        \"mountRoot\": \"{{target_mount_root}}\",\n        \"mountId\": \"{{clone_mount_id}}\",\n        \"attach\": {\n            \"sqlInstance\": \"localhost\",\n            \"skipPartitionAssign\": true,\n            \"autoPair\": true,\n            \"dbSelection\": \"ALL\",\n            \"dbPrefix\": \"ISCSI_\"\n        }\n    }\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Connects the clone's target, mounts the volume at `<target_mount_root>\\clones\\<clone_mount_id>`, and attaches the databases it finds, under the prefix the ingest used."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const id = j ? (j.result&&(j.result.job_id||j.result.id)) : null;",
											"if(id){pm.collectionVariables.set(\"job_id\",id);console.log(\"job_id =\",id)}",
											"else{console.warn(\"No job_id in the response:\", j && j.message)}"
										]
									}
								}
							]
						},
						{
							"name": "10. Poll the mount job",
							"request": {
								"method": "GET",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									}
								],
								"url": {
									"raw": "{{url}}/agent-job?job_id={{job_id}}&include_events=1",
									"host": [
										"{{url}}"
									],
									"path": [
										"agent-job"
									],
									"query": [
										{
											"key": "job_id",
											"value": "{{job_id}}"
										},
										{
											"key": "include_events",
											"value": "1"
										}
									]
								},
								"description": "Send again until the mount job reaches a final state."
							},
							"event": [
								{
									"listen": "test",
									"script": {
										"type": "text/javascript",
										"exec": [
											"let j; try{j=pm.response.json()}catch(e){}",
											"const job = j && j.result;",
											"if(job){console.log(\"state =\", job.state, \"|\", job.message||\"\")}"
										]
									}
								}
							]
						},
						{
							"name": "11. Mark the workflow complete",
							"request": {
								"method": "PATCH",
								"header": [
									{
										"key": "username",
										"value": "{{username}}"
									},
									{
										"key": "api-key",
										"value": "{{api-key}}"
									},
									{
										"key": "Content-Type",
										"value": "application/json"
									}
								],
								"url": {
									"raw": "{{url}}/workflow/{{workflow_id}}",
									"host": [
										"{{url}}"
									],
									"path": [
										"workflow",
										"{{workflow_id}}"
									]
								},
								"body": {
									"mode": "raw",
									"raw": "{\n    \"state\": \"completed\"\n}",
									"options": {
										"raw": {
											"language": "json"
										}
									}
								},
								"description": "Refused with **409** after a step has failed; pass `\"force\": true` to override. Run this folder again with a different `clone_base` and `target_agent_id` to put another copy on another host, with nothing ingested or transferred again."
							}
						}
					]
				}
			]
		},
		{
			"name": "Workflows",
			"description": "List, read and remove onboarding workflows. Creating and running a workflow is in Onboarding (API).",
			"item": [
				{
					"name": "List workflows",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/workflow",
							"host": [
								"{{url}}"
							],
							"path": [
								"workflow"
							]
						},
						"description": "Lists workflows. Optional query: `state`, `created_by`, `workflow_type`, `source_mode`, `target_mode`, `transport_mode`."
					},
					"response": []
				},
				{
					"name": "Show a workflow",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/workflow/{{workflow_id}}",
							"host": [
								"{{url}}"
							],
							"path": [
								"workflow",
								"{{workflow_id}}"
							]
						},
						"description": "One workflow with its steps, parts, jobs and dataset IQNs. The response includes the workflow's saved secrets, so treat it as sensitive."
					},
					"response": []
				},
				{
					"name": "Cleanup candidates",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/workflow/{{workflow_id}}/cleanup-candidates",
							"host": [
								"{{url}}"
							],
							"path": [
								"workflow",
								"{{workflow_id}}",
								"cleanup-candidates"
							]
						},
						"description": "The sources, snapshots and clones a cleanup delete of this workflow would destroy."
					},
					"response": []
				},
				{
					"name": "Delete a workflow",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/workflow/{{workflow_id}}?purge=1&cleanup=1",
							"host": [
								"{{url}}"
							],
							"path": [
								"workflow",
								"{{workflow_id}}"
							],
							"query": [
								{
									"key": "purge",
									"value": "1"
								},
								{
									"key": "cleanup",
									"value": "1"
								}
							]
						},
						"description": "Without query parameters a running workflow is cancelled. `purge=1` removes the record; with `cleanup=1` it also destroys the workflow's objects (see Cleanup candidates); `force=1` skips the in-use checks."
					},
					"response": []
				}
			]
		},
		{
			"name": "agents",
			"description": "Enrollment tokens and agent removal. Enrolling and running agent jobs is in Onboarding (API).",
			"item": [
				{
					"name": "List enrollment tokens",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/agent-token?active_only=1",
							"host": [
								"{{url}}"
							],
							"path": [
								"agent-token"
							],
							"query": [
								{
									"key": "active_only",
									"value": "1"
								}
							]
						},
						"description": "Admin only. Lists enrollment tokens. Active tokens only by default; `active_only=0` also lists used, expired and revoked tokens."
					},
					"response": []
				},
				{
					"name": "Revoke an enrollment token",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/agent-token",
							"host": [
								"{{url}}"
							],
							"path": [
								"agent-token"
							]
						},
						"description": "Admin only. Revokes an enrollment token.",
						"body": {
							"mode": "raw",
							"raw": "{\n    \"token_id\": \"{{token_id}}\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						}
					},
					"response": []
				},
				{
					"name": "Remove an agent",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/agent",
							"host": [
								"{{url}}"
							],
							"path": [
								"agent"
							]
						},
						"description": "Admin only. Removes an agent. The host must enroll again to be used.",
						"body": {
							"mode": "raw",
							"raw": "{\n    \"agent_id\": \"{{target_agent_id}}\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						}
					},
					"response": []
				}
			]
		},
		{
			"name": "objects",
			"description": "Delete several sources, snapshots and clones in one call.",
			"item": [
				{
					"name": "Destroy objects",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/object/destroy",
							"host": [
								"{{url}}"
							],
							"path": [
								"object",
								"destroy"
							]
						},
						"description": "Destroys several objects at once. Each entry names its `kind` (`source`, `snapshot` or `clone`), `pool_name` and `name`. Objects in use by a workflow are refused unless `force` is true.",
						"body": {
							"mode": "raw",
							"raw": "{\n    \"objects\": [\n        {\n            \"kind\": \"snapshot\",\n            \"pool_name\": \"vme-pool\",\n            \"name\": \"sales@nightly\"\n        },\n        {\n            \"kind\": \"clone\",\n            \"pool_name\": \"vme-pool\",\n            \"name\": \"sales-clone\"\n        }\n    ],\n    \"force\": false\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						}
					},
					"response": []
				}
			]
		},
		{
			"name": "active license",
			"item": [
				{
					"name": "key/get",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/key/get",
							"host": [
								"{{url}}"
							],
							"path": [
								"key",
								"get"
							]
						},
						"description": "Admin only. Returns this appliance's receiver key."
					},
					"response": []
				},
				{
					"name": "key/drop",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"secret\": \"{{licence_key}}\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/key/drop",
							"host": [
								"{{url}}"
							],
							"path": [
								"key",
								"drop"
							]
						},
						"description": "Admin only. Installs a licence key. Put your licence key in the `licence_key` variable."
					},
					"response": []
				}
			],
			"description": "Licence keys. Admin only."
		},
		{
			"name": "pool",
			"item": [
				{
					"name": "pool/show",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/pool/show",
							"host": [
								"{{url}}"
							],
							"path": [
								"pool",
								"show"
							],
							"query": [
								{
									"key": "properties",
									"value": "name,size,frag",
									"disabled": true
								},
								{
									"key": "properties",
									"value": "cap",
									"disabled": true
								}
							]
						},
						"description": "Lists the ZFS pools and their properties."
					},
					"response": []
				},
				{
					"name": "pool/status",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/pool/status?name=vme-pool",
							"host": [
								"{{url}}"
							],
							"path": [
								"pool",
								"status"
							],
							"query": [
								{
									"key": "name",
									"value": "vme-pool"
								}
							]
						},
						"description": "Pool status and health. Query `name`: the pool."
					},
					"response": []
				},
				{
					"name": "pool/history",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/pool/history?name=vme-pool",
							"host": [
								"{{url}}"
							],
							"path": [
								"pool",
								"history"
							],
							"query": [
								{
									"key": "name",
									"value": "vme-pool"
								}
							]
						},
						"description": "ZFS command history for a pool. Query `name`: the pool."
					},
					"response": []
				},
				{
					"name": "pool/create",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"vme-pool\",\n    \"device\": [\n        \"nvme1n1\"\n    ]\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/pool/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"pool",
								"create"
							]
						},
						"description": "Creates a pool on one or more disks (`device`: the disk names from `zfs/disks`)."
					},
					"response": []
				},
				{
					"name": "pool/register",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"vme-pool\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/pool/register",
							"host": [
								"{{url}}"
							],
							"path": [
								"pool",
								"register"
							]
						},
						"description": "Registers an existing pool with vME."
					},
					"response": []
				},
				{
					"name": "pool/create/status",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/pool/create/status",
							"host": [
								"{{url}}"
							],
							"path": [
								"pool",
								"create",
								"status"
							]
						},
						"description": "Internal status rows for pool creation."
					},
					"response": []
				},
				{
					"name": "pool/destroy",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"vme-pool\",\n    \"force\": true\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/pool/destroy",
							"host": [
								"{{url}}"
							],
							"path": [
								"pool",
								"destroy"
							]
						},
						"description": "Destroys a pool and everything in it. Cannot be undone."
					},
					"response": []
				},
				{
					"name": "zfs/disks",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/zfs/disks",
							"host": [
								"{{url}}"
							],
							"path": [
								"zfs",
								"disks"
							]
						},
						"description": "Lists the disks the appliance can build pools on."
					},
					"response": []
				}
			],
			"description": "ZFS pools."
		},
		{
			"name": "source",
			"item": [
				{
					"name": "source/show",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/source/show",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"show"
							],
							"query": [
								{
									"key": "properties",
									"value": "used,Refer",
									"disabled": true
								},
								{
									"key": "source_name",
									"value": "vme-pool/sources",
									"disabled": true
								},
								{
									"key": "properties",
									"value": "compression,used,quota",
									"disabled": true
								},
								{
									"key": "source_name",
									"value": "sales-pool/sources/t",
									"disabled": true
								},
								{
									"key": "pool_name",
									"value": "vme-pool",
									"disabled": true
								}
							]
						},
						"description": "Each source in the result carries `guid`, the dataset's ZFS guid, which ZFS assigns when the dataset is created and never changes. It identifies the dataset whatever it is called, so it survives a rename.\n\nA source with an iSCSI export also carries `iqn_name`, the exact name of the target it exports, and `iqn_scheme`. `iqn_scheme` is `guid` when the IQN ends in a `g-<guid>` token, and `name` for an export created before the token existed. Scope host-side work with `iqn_name` rather than deriving a fragment from the dataset name: a derived fragment is lossy, and two datasets can produce the same one."
					},
					"response": []
				},
				{
					"name": "source/status",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/source/status",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"status"
							]
						},
						"description": "Internal status rows for sources."
					},
					"response": []
				},
				{
					"name": "source/create",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"name\": \"sales\",\n    \"compression\": \"lzjb\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/source/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"create"
							]
						},
						"description": "Creates a source dataset. `database_method` `network` with `network_info.type` `iscsi` or `nfs` exports it to a database host."
					},
					"response": []
				},
				{
					"name": "source/create sharenfs",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"name\": \"sales\",\n    \"compression\": \"lzjb\",\n    \"database_method\": \"network\",\n    \"network_info\": {\n        \"type\": \"nfs\"\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/source/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"create"
							]
						},
						"description": "Creates a source dataset. `database_method` `network` with `network_info.type` `iscsi` or `nfs` exports it to a database host."
					},
					"response": []
				},
				{
					"name": "source/create iSCSI",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"name\": \"sales\",\n    \"compression\": \"lzjb\",\n    \"database_method\": \"network\",\n    \"network_info\": {\n        \"type\": \"iscsi\",\n        \"auto_grow\": true,\n        \"auto_grow_max_gb\": 16384\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/source/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"create"
							]
						},
						"description": "Creates a source dataset. `database_method` `network` with `network_info.type` `iscsi` or `nfs` exports it to a database host."
					},
					"response": []
				},
				{
					"name": "source/create iSCSI data",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"name\": \"sales\",\n    \"compression\": \"off\",\n    \"database_method\": \"network\",\n    \"network_info\": {\n        \"type\": \"iscsi\",\n        \"setting\": [\n            \"dedup=off\",\n            \"logbias=latency\",\n            \"sync=disabled\"\n        ],\n        \"vsize\": 4\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/source/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"create"
							]
						},
						"description": "Creates a source dataset. `database_method` `network` with `network_info.type` `iscsi` or `nfs` exports it to a database host."
					},
					"response": []
				},
				{
					"name": "source/modify",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"name\": \"sales\",\n    \"property\": {\n        \"quota\": \"5G\",\n        \"dbtype\": \"mysql\",\n        \"compression\": \"gzip\"\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/source/modify",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"modify"
							]
						},
						"description": "Changes a source's ZFS properties (`property`). The database method cannot be changed after creation."
					},
					"response": []
				},
				{
					"name": "source/rename",
					"request": {
						"method": "PUT",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"currentname\": \"sales\",\n    \"newname\": \"sales-renamed\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/source/rename",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"rename"
							]
						},
						"description": "Renames the dataset and moves its record.\n\nA source exported over iSCSI can be renamed while a host has its LUNs mounted. The export's names are built from the dataset's guid, not its path, so the target keeps the IQN the host connected to and the session is unaffected. The appliance repairs the device path in the saved target configuration, so the export also survives a restart. The response repeats `iqn_name` and `backstore_name` to make the point that they did not change.\n\nRefused with 409 while an unfinished onboarding workflow names the dataset: that workflow would act on it under the name it recorded. A finished workflow keeps the name it recorded, and the response lists those under `workflows_holding_the_previous_name`; cleanup treats a dataset that is no longer there as already gone.\n\nRefused for NFS, whose export path is the dataset's mountpoint, so renaming would move the path clients have mounted."
					},
					"response": []
				},
				{
					"name": "source/destroy",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"source_name\": \"sales\",\n    \"recursive\": false\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/source/destroy",
							"host": [
								"{{url}}"
							],
							"path": [
								"source",
								"destroy"
							]
						},
						"description": "Destroys a source. `recursive` also destroys its snapshots and clones."
					},
					"response": []
				}
			],
			"description": "Sources: the datasets a database is onboarded into."
		},
		{
			"name": "snapshot",
			"item": [
				{
					"name": "snapshot/show",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/snapshot/show",
							"host": [
								"{{url}}"
							],
							"path": [
								"snapshot",
								"show"
							],
							"query": [
								{
									"key": "pool_name",
									"value": "sales-pool",
									"disabled": true
								},
								{
									"key": "source_name",
									"value": "vme-pool/sources/demo",
									"disabled": true
								},
								{
									"key": "sort",
									"value": "true",
									"disabled": true
								},
								{
									"key": "properties",
									"value": "used,refer",
									"disabled": true
								}
							]
						},
						"description": "Lists snapshots. Optional query: `pool_name`, `source_name`, `sort`."
					},
					"response": []
				},
				{
					"name": "snapshot/create",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"source_name\": \"sales\",\n    \"name\": \"nightly\",\n    \"recursive\": false\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/snapshot/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"snapshot",
								"create"
							]
						},
						"description": "Takes a snapshot. For a source attached to a SQL host with the agent, vME coordinates with the host and answers 202 with a `task_id` (follow it with `GET /snapshot/task/<task_id>`); send `skip_host: true` to skip the host. Use `snapof: \"clone\"` to snapshot a clone."
					},
					"response": []
				},
				{
					"name": "snapshot/rename",
					"request": {
						"method": "PUT",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"source_name\": \"sales-renamed\",\n    \"currentname\": \"nightly\",\n    \"newname\": \"nightly-renamed\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/snapshot/rename",
							"host": [
								"{{url}}"
							],
							"path": [
								"snapshot",
								"rename"
							]
						},
						"description": "Renames a snapshot."
					},
					"response": []
				},
				{
					"name": "snapshot/destroy",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"source_name\": \"sales\",\n    \"snapshot_name\": \"nightly\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/snapshot/destroy",
							"host": [
								"{{url}}"
							],
							"path": [
								"snapshot",
								"destroy"
							]
						},
						"description": "Destroys a snapshot. Refused while clones depend on it."
					},
					"response": []
				},
				{
					"name": "snapshot/rollback",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"source_name\": \"vme-pool/clones/sales-clone\",\n    \"snapshot_name\": \"nightly\",\n    \"force\": true\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/snapshot/rollback",
							"host": [
								"{{url}}"
							],
							"path": [
								"snapshot",
								"rollback"
							]
						},
						"description": "Rolls a source or clone back to a snapshot. Coordinated with the host like snapshot create."
					},
					"response": []
				}
			],
			"description": "Snapshots, rollback and rename. Snapshot create and rollback are coordinated with the SQL host when the source is attached through the agent."
		},
		{
			"name": "clone",
			"item": [
				{
					"name": "clone/show",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/clone/show",
							"host": [
								"{{url}}"
							],
							"path": [
								"clone",
								"show"
							],
							"query": [
								{
									"key": "properties",
									"value": "refer,Used",
									"disabled": true
								},
								{
									"key": "pool_name",
									"value": "vme-pool",
									"disabled": true
								},
								{
									"key": "source_name",
									"value": "vme-pool/sources/sales",
									"disabled": true
								},
								{
									"key": "source_name",
									"value": "vme-pool/sources/sales2",
									"disabled": true
								},
								{
									"key": "snapshot_name",
									"value": "vme-pool/sources/sales@nightly,vme-pool/sources/sales2@nightly",
									"disabled": true
								},
								{
									"key": "snapshot_name",
									"value": "vme-pool/sources/sales-create@nightly",
									"disabled": true
								},
								{
									"key": "pool_name",
									"value": "sales-pool",
									"disabled": true
								},
								{
									"key": "source_name",
									"value": "vme-pool/sources/demosource",
									"disabled": true
								},
								{
									"key": "properties",
									"value": "compression,quota",
									"disabled": true
								}
							]
						},
						"description": "Each clone in the result carries `guid`, the dataset's ZFS guid, which ZFS assigns when the dataset is created and never changes. It identifies the dataset whatever it is called, so it survives a rename.\n\nA clone with an iSCSI export also carries `iqn_name`, the exact name of the target it exports, and `iqn_scheme`. `iqn_scheme` is `guid` when the IQN ends in a `g-<guid>` token, and `name` for an export created before the token existed. Scope host-side work with `iqn_name` rather than deriving a fragment from the dataset name: a derived fragment is lossy, and two datasets can produce the same one."
					},
					"response": []
				},
				{
					"name": "clone/status",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/clone/status",
							"host": [
								"{{url}}"
							],
							"path": [
								"clone",
								"status"
							]
						},
						"description": "Internal status rows for clones."
					},
					"response": []
				},
				{
					"name": "clone/create",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"source_name\": \"sales\",\n    \"snapshot_name\": \"nightly\",\n    \"name\": \"sales-clone\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/clone/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"clone",
								"create"
							]
						},
						"description": "Creates a clone of a snapshot. `name` is optional. `database_method` `network` exports it over iSCSI or NFS."
					},
					"response": []
				},
				{
					"name": "clone/create iSCSI",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"source_name\": \"sales\",\n    \"snapshot_name\": \"nightly\",\n    \"name\": \"sales-clone\",\n    \"compression\": \"off\",\n    \"database_method\": \"network\",\n    \"network_info\": {\n        \"type\": \"iscsi\"\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/clone/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"clone",
								"create"
							]
						},
						"description": "Creates a clone of a snapshot. `name` is optional. `database_method` `network` exports it over iSCSI or NFS."
					},
					"response": []
				},
				{
					"name": "clone/modify",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"name\": \"sales-clone\",\n    \"property\": {\n        \"quota\": \"5G\",\n        \"dbtype\": \"mysql\",\n        \"compression\": \"gzip\"\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/clone/modify",
							"host": [
								"{{url}}"
							],
							"path": [
								"clone",
								"modify"
							]
						},
						"description": "Changes a clone's ZFS properties (`property`). The database method cannot be changed after creation."
					},
					"response": []
				},
				{
					"name": "clone/rename",
					"request": {
						"method": "PUT",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"currentname\": \"sales-clone\",\n    \"newname\": \"clone-2\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/clone/rename",
							"host": [
								"{{url}}"
							],
							"path": [
								"clone",
								"rename"
							]
						},
						"description": "Renames the dataset and moves its record.\n\nA clone exported over iSCSI can be renamed while a host has its LUNs mounted. The export's names are built from the dataset's guid, not its path, so the target keeps the IQN the host connected to and the session is unaffected. The appliance repairs the device path in the saved target configuration, so the export also survives a restart. The response repeats `iqn_name` and `backstore_name` to make the point that they did not change.\n\nRefused with 409 while an unfinished onboarding workflow names the dataset: that workflow would act on it under the name it recorded. A finished workflow keeps the name it recorded, and the response lists those under `workflows_holding_the_previous_name`; cleanup treats a dataset that is no longer there as already gone.\n\nRefused for NFS, whose export path is the dataset's mountpoint, so renaming would move the path clients have mounted."
					},
					"response": []
				},
				{
					"name": "clone/destroy",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"clone_name\": \"sales-clone\",\n    \"recursive\": false\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/clone/destroy",
							"host": [
								"{{url}}"
							],
							"path": [
								"clone",
								"destroy"
							]
						},
						"description": "Destroys a clone."
					},
					"response": []
				}
			],
			"description": "Clones of snapshots."
		},
		{
			"name": "docker",
			"item": [
				{
					"name": "docker/info",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/docker/info",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"info"
							]
						},
						"description": "Docker version on the appliance."
					},
					"response": []
				},
				{
					"name": "docker/image/list",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/docker/image/list",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"image",
								"list"
							]
						},
						"description": "Lists the container images on the appliance."
					},
					"response": []
				},
				{
					"name": "docker/image/status",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/docker/image/status",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"image",
								"status"
							]
						},
						"description": "Internal status rows for images."
					},
					"response": []
				},
				{
					"name": "docker/image/pull",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"repository\": \"mcr.microsoft.com/mssql/server\",\n    \"tag\": \"2022-latest\",\n    \"dbtype\": \"mssql\",\n    \"credential\": {\n        \"username\": \"\",\n        \"password\": \"\"\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/image/pull",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"image",
								"pull"
							]
						},
						"description": "Pulls an image from a registry. Leave `credential` blank for public images."
					},
					"response": []
				},
				{
					"name": "docker/image/register",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"mysql:latest\",\n    \"dbtype\": \"mysql\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/image/register",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"image",
								"register"
							]
						},
						"description": "Registers an image already on the appliance."
					},
					"response": []
				},
				{
					"name": "docker/image/save",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"image\": \"mysql:latest\",\n    \"filename\": \"demo.tar\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/image/save",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"image",
								"save"
							]
						},
						"description": "Saves an image to a file on the appliance."
					},
					"response": []
				},
				{
					"name": "docker/image/load",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"filename\": \"demo.tar\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/image/load",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"image",
								"load"
							]
						},
						"description": "Loads an image from a file on the appliance."
					},
					"response": []
				},
				{
					"name": "docker/image/remove",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"image\": \"mongo:latest\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/image/remove",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"image",
								"remove"
							]
						},
						"description": "Removes an image."
					},
					"response": []
				},
				{
					"name": "docker/image/detail",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/docker/image/detail?name=container-registry.oracle.com/database/enterprise:19.3.0.0",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"image",
								"detail"
							],
							"query": [
								{
									"key": "name",
									"value": "container-registry.oracle.com/database/enterprise:19.3.0.0"
								}
							]
						},
						"description": "Image details. Query `name`."
					},
					"response": []
				},
				{
					"name": "docker/container/list",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/docker/container/list",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"container",
								"list"
							]
						},
						"description": "Lists containers."
					},
					"response": []
				},
				{
					"name": "docker/container/create",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"image\": \"mysql\",\n    \"name\": \"sales-mysql\",\n    \"volumes\": [\n        \"/vme-pool/clones/sales-clone:/var/lib/mysql\"\n    ],\n    \"ports\": \"1522:22,1599:1521,1580:8080\",\n    \"environment\": []\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/container/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"container",
								"create"
							]
						},
						"description": "Creates a container, optionally mounting a source or clone as a volume."
					},
					"response": []
				},
				{
					"name": "docker/container/start",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"a11941b310dfaed2fdb1087c0bd8b33025086885aea6ebbc85cdebe5b36c54da\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/container/start",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"container",
								"start"
							]
						},
						"description": "Starts a container."
					},
					"response": []
				},
				{
					"name": "docker/container/stop",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"a11941b310dfaed2fdb1087c0bd8b33025086885aea6ebbc85cdebe5b36c54da\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/container/stop",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"container",
								"stop"
							]
						},
						"description": "Stops a container."
					},
					"response": []
				},
				{
					"name": "docker/container/remove",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"sales-mysql\",\n    \"volume\": true\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/container/remove",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"container",
								"remove"
							]
						},
						"description": "Removes a container. `volume: true` also removes its volumes."
					},
					"response": []
				},
				{
					"name": "docker/container/exec",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"mymariadb\",\n    \"command\": \"mysql --user=root --password=\\\"default123\\\" -e \\\"source /mnt/nation.sql\\\"\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/docker/container/exec",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"container",
								"exec"
							]
						},
						"description": "Runs a command in a container."
					},
					"response": []
				},
				{
					"name": "docker/container/detail",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/docker/container/detail?name=sales-mysql",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"container",
								"detail"
							],
							"query": [
								{
									"key": "name",
									"value": "mymariadb",
									"disabled": true
								},
								{
									"key": "name",
									"value": "con2",
									"disabled": true
								},
								{
									"key": "name",
									"value": "salesa"
								}
							]
						},
						"description": "Container details. Query `name`."
					},
					"response": []
				},
				{
					"name": "docker/container/log",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/docker/container/log?name=sales-mysql",
							"host": [
								"{{url}}"
							],
							"path": [
								"docker",
								"container",
								"log"
							],
							"query": [
								{
									"key": "name",
									"value": "mymariadb",
									"disabled": true
								},
								{
									"key": "name",
									"value": "con2",
									"disabled": true
								},
								{
									"key": "name",
									"value": "salesa"
								}
							]
						},
						"description": "Container log. Query `name`."
					},
					"response": []
				}
			],
			"description": "Container images and containers on the appliance."
		},
		{
			"name": "db",
			"item": [
				{
					"name": "db/backup",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/db/backup",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"backup"
							]
						},
						"description": "Lists the backup files on the appliance."
					},
					"response": []
				},
				{
					"name": "db/backup",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"dataset\": \"vme-pool/sources/sales\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/backup",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"backup"
							]
						},
						"description": "Writes a dataset to a backup file on the appliance (`dest`, `filename` optional)."
					},
					"response": []
				},
				{
					"name": "db/receive",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pool_name\": \"vme-pool\",\n    \"dataset_name\": \"sales-restored\",\n    \"dbtype\": \"unknown\",\n    \"src\": \"vme-pool-sources-sales@nightly-20261020.vmebk\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/receive",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"receive"
							]
						},
						"description": "Restores a dataset from a backup file (`src`)."
					},
					"response": []
				},
				{
					"name": "db/send - pool2pool",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"type\": \"pool2pool\",\n    \"dataset\": \"vme-pool/sources/sales@nightly\",\n    \"receiver\": {\n        \"pool_name\": \"vme-pool\",\n        \"dataset_name\": \"sales-copy\",\n        \"dbtype\": \"unknown\"\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/send",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"send"
							]
						},
						"description": "Sends a snapshot to another pool (`pool2pool`) or another vME (`sys2sys`). Returns a `task_id` to follow with `db/send/status`."
					},
					"response": []
				},
				{
					"name": "db/send - sys2sys",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"type\": \"sys2sys\",\n    \"dataset\": \"vme-pool/sources/sales@nightly\",\n    \"receiver\": {\n        \"address\": \"https://{{target_host}}\",\n        \"username\": \"{{target_username}}\",\n        \"api-key\": \"{{target_api_key}}\",\n        \"pool_name\": \"{{target_pool}}\",\n        \"dataset_name\": \"sales-copy\",\n        \"dbtype\": \"unknown\"\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/send",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"send"
							]
						},
						"description": "Sends a snapshot to another pool (`pool2pool`) or another vME (`sys2sys`). Returns a `task_id` to follow with `db/send/status`."
					},
					"response": []
				},
				{
					"name": "db/send/cancel",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"task_id\": \"{{task_id}}\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/send/cancel",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"send",
								"cancel"
							]
						},
						"description": "Cancels a running send."
					},
					"response": []
				},
				{
					"name": "tasks/:task_id",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/tasks/:task_id",
							"host": [
								"{{url}}"
							],
							"path": [
								"tasks",
								":task_id"
							],
							"variable": [
								{
									"key": "task_id",
									"value": "YOUR_TASK_ID"
								}
							]
						},
						"description": "State of a background task. Set the `task_id` variable."
					},
					"response": []
				},
				{
					"name": "db/connect",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"dbtype\": \"mssql\",\n    \"host\": \"localhost\",\n    \"user\": \"sa\",\n    \"password\": \"YourDatabasePassword\",\n    \"port\": 8881\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/connect",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"connect"
							]
						},
						"description": "Tests a database connection from the appliance."
					},
					"response": []
				},
				{
					"name": "db/network/create",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"full_name\": \"vme-pool/clones/sales-clone\",\n    \"client_address\": \"0.0.0.0\",\n    \"client_username\": \"admin\",\n    \"client_password\": \"admin\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/network/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"network",
								"create"
							]
						},
						"description": "Exports a source or clone (`full_name`) over iSCSI or NFS. iSCSI: `client_address` (default 0.0.0.0), `client_username` and `client_password` (default admin). NFS: `client_address`, `anonuid` (default 117), `anongid` (default 122)."
					},
					"response": []
				},
				{
					"name": "db/network/create nfs",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"full_name\": \"vme-pool/sources/sales\",\n    \"client_address\": \"0.0.0.0\",\n    \"anonuid\": 117,\n    \"anongid\": 122\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/network/create",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"network",
								"create"
							]
						},
						"description": "Exports a source or clone (`full_name`) over iSCSI or NFS. iSCSI: `client_address` (default 0.0.0.0), `client_username` and `client_password` (default admin). NFS: `client_address`, `anonuid` (default 117), `anongid` (default 122)."
					},
					"response": []
				},
				{
					"name": "db/network/delete",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"full_name\": \"vme-pool/clones/sales-clone\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/db/network/delete",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"network",
								"delete"
							]
						},
						"description": "Removes the iSCSI or NFS export of a source or clone (`full_name`)."
					},
					"response": []
				},
				{
					"name": "db/send/status",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/db/send/status?task_id={{task_id}}",
							"host": [
								"{{url}}"
							],
							"path": [
								"db",
								"send",
								"status"
							],
							"query": [
								{
									"key": "task_id",
									"value": "{{task_id}}",
									"description": "Task ID from db/send response"
								},
								{
									"key": "dataset",
									"value": "pool/sources/dataset",
									"disabled": true,
									"description": "Alternative: query by dataset name"
								}
							]
						},
						"description": "Progress of a send. Query `task_id`."
					},
					"response": []
				}
			],
			"description": "Backup, restore, send between pools and appliances, database connections and iSCSI or NFS exports."
		},
		{
			"name": "user",
			"item": [
				{
					"name": "user",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/user",
							"host": [
								"{{url}}"
							],
							"path": [
								"user"
							]
						},
						"description": "Your own user profile, including your api-key."
					},
					"response": []
				},
				{
					"name": "login",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript",
								"packages": {},
								"requests": {}
							}
						}
					],
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"admin\",\n    \"password\": \"admin\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/login",
							"host": [
								"{{url}}"
							],
							"path": [
								"login"
							]
						},
						"description": "Logs in with username and password and returns your `api-key`. Put it in the `api-key` variable; every other request sends it with `username`."
					},
					"response": []
				},
				{
					"name": "admin/user/add",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"newuser\",\n    \"password\": \"password123\",\n    \"name\": \"New User\",\n    \"mail\": \"newuser@example.com\",\n    \"group_id\": 1,\n    \"auth_type\": \"local\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/admin/user/add",
							"host": [
								"{{url}}"
							],
							"path": [
								"admin",
								"user",
								"add"
							]
						},
						"description": "Admin only. Adds a user. Set `group_id`: 0 is the administrators group."
					},
					"response": []
				},
				{
					"name": "admin/user/modify",
					"request": {
						"method": "PUT",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"targetuser\",\n    \"name\": \"Updated Name\",\n    \"mail\": \"updated@example.com\",\n    \"group_id\": 2,\n    \"rotate_api_key\": false\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/admin/user/modify",
							"host": [
								"{{url}}"
							],
							"path": [
								"admin",
								"user",
								"modify"
							]
						},
						"description": "Admin only. Changes a user's name, mail, group, auth type or password, or rotates their api-key."
					},
					"response": []
				},
				{
					"name": "admin/user/list",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/admin/user/list",
							"host": [
								"{{url}}"
							],
							"path": [
								"admin",
								"user",
								"list"
							]
						},
						"description": "Admin only. Lists users."
					},
					"response": []
				},
				{
					"name": "admin/user/delete",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"jane\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/admin/user/delete",
							"host": [
								"{{url}}"
							],
							"path": [
								"admin",
								"user",
								"delete"
							]
						},
						"description": "Admin only. Deletes a user. The last administrator cannot be deleted."
					},
					"response": []
				},
				{
					"name": "user/setgroup",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"jane\",\n    \"group_id\": 0\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/setgroup",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"setgroup"
							]
						},
						"description": "Admin only. Moves a user to another group."
					},
					"response": []
				},
				{
					"name": "user/group",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/user/group",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"group"
							]
						},
						"description": "Admin only. Lists the user groups."
					},
					"response": []
				},
				{
					"name": "user/group/add",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"group_id\": 3,\n    \"group_name\": \"New Group\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/group/add",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"group",
								"add"
							]
						},
						"description": "Admin only. Adds a user group."
					},
					"response": []
				},
				{
					"name": "user/group/delete",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"group_id\": 3\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/group/delete",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"group",
								"delete"
							]
						},
						"description": "Admin only. Deletes a user group."
					},
					"response": []
				},
				{
					"name": "add-user",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript",
								"packages": {},
								"requests": {}
							}
						}
					],
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"jane\",\n    \"password\": \"ChangeMe-123\",\n    \"name\": \"Jane Doe\",\n    \"mail\": \"jane.doe@example.com\",\n    \"group_id\": 0\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/add",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"add"
							]
						},
						"description": "Admin only. Adds a user. Set `group_id`: if it is left out the user is added to the administrators group (0)."
					},
					"response": []
				},
				{
					"name": "modify-user",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript",
								"packages": {},
								"requests": {}
							}
						}
					],
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"adminuser\",\n    \"current_password\": \"admin123\",\n    \"password\": {\n        \"current\": \"admin123\",\n        \"new\": \"admin1234\",\n        \"confirm\": \"admin1234\"\n    },\n    \"name\": \"Jane Doe\",\n    \"mail\": \"jane.doe@example.com\",\n    \"rotate_api_key\": true\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/modify",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"modify"
							]
						},
						"description": "Changes your own name, mail or password. Authenticated by `current_password` in the body, not by the headers."
					},
					"response": []
				},
				{
					"name": "delete-user",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript",
								"packages": {},
								"requests": {}
							}
						}
					],
					"request": {
						"method": "DELETE",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"adminuser\",\n    \"password\": \"admin123\",\n    \"confirm_text\": \"DELETE adminuser\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/delete",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"delete"
							]
						},
						"description": "Deletes your own account. Authenticated by the account's password. Administrator accounts are refused; use `admin/user/delete`."
					},
					"response": []
				},
				{
					"name": "changepass",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript"
							}
						}
					],
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"{{username}}\",\n    \"password\": \"your-current-password\",\n    \"new_password\": \"your-new-password\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/changepass",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"changepass"
							]
						},
						"description": "Changes your own password."
					},
					"response": []
				}
			],
			"description": "Login, your own account, and user administration."
		},
		{
			"name": "LDAP",
			"item": [
				{
					"name": "ldap-get",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/user/ldap",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"ldap"
							]
						},
						"description": "Admin only. Shows the LDAP settings."
					},
					"response": []
				},
				{
					"name": "ldap-create",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"server\": \"ldap.company.com\",\n    \"port\": 389,\n    \"bind_dn\": \"cn=readonly,dc=company,dc=com\",\n    \"bind_password\": \"secret\",\n    \"user_search_base\": \"ou=users,dc=company,dc=com\",\n    \"user_filter\": \"(uid={})\",\n    \"vme_attrs\": {\n        \"username\": \"uid\",\n        \"name\": \"cn\",\n        \"mail\": \"mail\"\n    }\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/ldap",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"ldap"
							]
						},
						"description": "Admin only. Creates the LDAP settings."
					},
					"response": []
				},
				{
					"name": "ldap-update",
					"request": {
						"method": "PUT",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"server\": \"ldap.company.com\",\n    \"port\": 636\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/ldap",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"ldap"
							]
						},
						"description": "Admin only. Updates the LDAP settings."
					},
					"response": []
				},
				{
					"name": "ldap-delete",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/user/ldap",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"ldap"
							]
						},
						"description": "Admin only. Removes the LDAP settings."
					},
					"response": []
				},
				{
					"name": "ldap-test",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"server\": \"ldap.company.com\",\n    \"port\": 389,\n    \"bind_dn\": \"cn=readonly,dc=company,dc=com\",\n    \"bind_password\": \"secret\",\n    \"user_search_base\": \"ou=users,dc=company,dc=com\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/ldap/test",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"ldap",
								"test"
							]
						},
						"description": "Admin only. Tests LDAP settings without saving them."
					},
					"response": []
				},
				{
					"name": "ldap-login",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript",
								"packages": {},
								"requests": {}
							}
						}
					],
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"adminuser\",\n    \"password\": \"admin123\",\n    \"method\": \"ldap\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/login",
							"host": [
								"{{url}}"
							],
							"path": [
								"login"
							]
						},
						"description": "Logs in with username and password and returns your `api-key`. Put it in the `api-key` variable; every other request sends it with `username`."
					},
					"response": []
				},
				{
					"name": "modify-user",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript",
								"packages": {},
								"requests": {}
							}
						}
					],
					"request": {
						"method": "POST",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"adminuser\",\n    \"current_password\": \"admin123\",\n    \"name\": \"Jane Doe\",\n    \"mail\": \"jane.doe@example.com\",\n    \"rotate_api_key\": true,\n    \"method\": \"ldap\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/modify",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"modify"
							]
						},
						"description": "Changes your own name, mail or password. Authenticated by `current_password` in the body, not by the headers."
					},
					"response": []
				},
				{
					"name": "delete-user",
					"event": [
						{
							"listen": "test",
							"script": {
								"exec": [
									""
								],
								"type": "text/javascript",
								"packages": {},
								"requests": {}
							}
						}
					],
					"request": {
						"method": "DELETE",
						"header": [],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"adminuser\",\n    \"password\": \"admin123\",\n    \"confirm_text\": \"DELETE adminuser\",\n    \"method\": \"ldap\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/user/delete",
							"host": [
								"{{url}}"
							],
							"path": [
								"user",
								"delete"
							]
						},
						"description": "Deletes your own account. Authenticated by the account's password. Administrator accounts are refused; use `admin/user/delete`."
					},
					"response": []
				}
			],
			"description": "LDAP settings and LDAP login. Admin only except login."
		},
		{
			"name": "auth",
			"item": [
				{
					"name": "auth/verify",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"username\": \"{{username}}\",\n    \"api_key\": \"{{api-key}}\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/auth/verify",
							"host": [
								"{{url}}"
							],
							"path": [
								"auth",
								"verify"
							]
						},
						"description": "Checks a `username` and `api_key` pair sent in the body."
					},
					"response": []
				}
			],
			"description": "Credential checks."
		},
		{
			"name": "iSCSI",
			"item": [
				{
					"name": "iscsi/chap/set",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"target_iqn\": \"iqn.2024-01.com.example:target\",\n    \"initiator_iqn\": \"iqn.2024-01.com.example:initiator\",\n    \"chap_user\": \"admin\",\n    \"chap_password\": \"your-chap-password\",\n    \"mutual_chap_password\": \"optional-mutual-password\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/iscsi/chap/set",
							"host": [
								"{{url}}"
							],
							"path": [
								"iscsi",
								"chap",
								"set"
							]
						},
						"description": "Sets mutual CHAP for an iSCSI target and initiator."
					},
					"response": []
				},
				{
					"name": "iscsi/chap/remove",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							},
							{
								"key": "Content-Type",
								"value": "application/json",
								"type": "text"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"target_iqn\": \"iqn.2024-01.com.example:target\",\n    \"initiator_iqn\": \"iqn.2024-01.com.example:initiator\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/iscsi/chap/remove",
							"host": [
								"{{url}}"
							],
							"path": [
								"iscsi",
								"chap",
								"remove"
							]
						},
						"description": "Removes CHAP and the ACL from an iSCSI target."
					},
					"response": []
				}
			],
			"description": "CHAP settings for iSCSI exports."
		},
		{
			"name": "Appliances (peer registry)",
			"description": "The other vME appliances this one sends snapshots to. Credentials are stored here once (the api-key encrypted), so a workflow's send step names an appliance instead of carrying its admin api-key. All admin-only.\n\nRun **Add an appliance** → **Establish trust** → **Test an appliance** in that order; each captures `peer_id` for the ones after it.",
			"item": [
				{
					"name": "List appliances",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"url": {
							"raw": "{{url}}/peer"
						},
						"description": "Every vME appliance registered on this one. `has_api_key` says whether a key is stored; the key itself is never returned."
					},
					"event": [
						{
							"listen": "test",
							"script": {
								"type": "text/javascript",
								"exec": [
									"let j; try{j=pm.response.json()}catch(e){}",
									"const rows = j && j.result || [];",
									"if(rows.length){pm.collectionVariables.set(\"peer_id\", rows[0].peer_id);console.log(\"peer_id =\", rows[0].peer_id)}"
								]
							}
						}
					]
				},
				{
					"name": "Add an appliance",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"name\": \"{{peer_name}}\",\n    \"base_url\": \"{{target_host}}\",\n    \"admin_username\": \"{{target_username}}\",\n    \"admin_api_key\": \"{{target_api_key}}\",\n    \"verify_tls\": false\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/peer"
						},
						"description": "`name`, `base_url` and `admin_api_key` are required. The api-key is encrypted at rest and never returned. Optional: `ssh_address` when SSH data transfer uses a different address than `base_url`, and `verify_tls` (default false, since appliances ship a self-signed certificate). A duplicate name answers 409."
					},
					"event": [
						{
							"listen": "test",
							"script": {
								"type": "text/javascript",
								"exec": [
									"let j; try{j=pm.response.json()}catch(e){}",
									"const p = j && j.result;",
									"if(p&&p.peer_id){pm.collectionVariables.set(\"peer_id\",p.peer_id);console.log(\"peer_id =\",p.peer_id)}"
								]
							}
						}
					]
				},
				{
					"name": "Show an appliance",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"url": {
							"raw": "{{url}}/peer/{{peer_id}}"
						},
						"description": "Shows one registered appliance."
					}
				},
				{
					"name": "Amend an appliance",
					"request": {
						"method": "PATCH",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"ssh_address\": \"10.0.0.20\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/peer/{{peer_id}}"
						},
						"description": "Any of `name`, `base_url`, `admin_username`, `admin_api_key`, `ssh_address`, `verify_tls`. Send `admin_api_key` only to replace the stored key."
					}
				},
				{
					"name": "Establish trust",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/peer/{{peer_id}}/trust"
						},
						"description": "Pushes this appliance's managed SSH public key to the peer, so snapshot transfers to it need no SSH setup by hand. The peer answers on its own `POST /peer/trust`."
					}
				},
				{
					"name": "Test an appliance",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/peer/{{peer_id}}/test"
						},
						"description": "Reachability, the peer's pools, its agent count and its vME version (read from the peer's `GET /info`). Answers **502** with a `result` report when the peer cannot be reached, and records `status`/`last_error` on the registry row either way."
					},
					"event": [
						{
							"listen": "test",
							"script": {
								"type": "text/javascript",
								"exec": [
									"let j; try{j=pm.response.json()}catch(e){}",
									"const r = j && j.result || {};",
									"console.log(\"reachable:\", r.reachable, \"| version:\", r.remote_version,",
									"            \"| pools:\", JSON.stringify((r.pools||[]).map(p=>p.name)));",
									"if((r.pools||[]).length){pm.collectionVariables.set(\"target_pool\", r.pools[0].name)}"
								]
							}
						}
					]
				},
				{
					"name": "List the appliance's pools",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"url": {
							"raw": "{{url}}/peer/{{peer_id}}/pools"
						},
						"description": "Proxied from the peer, using the credentials in the registry."
					}
				},
				{
					"name": "List the appliance's agents",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"url": {
							"raw": "{{url}}/peer/{{peer_id}}/agents"
						},
						"description": "Proxied from the peer, using the credentials in the registry."
					}
				},
				{
					"name": "Remove an appliance",
					"request": {
						"method": "DELETE",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"url": {
							"raw": "{{url}}/peer/{{peer_id}}"
						},
						"description": "Removes the registry row. Workflows that send to it need it registered again."
					}
				},
				{
					"name": "This appliance's peer identity",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"url": {
							"raw": "{{url}}/peer/identity"
						},
						"description": "This appliance's own managed SSH public key and its fingerprint. Generated on first call. Use it to trust this appliance from somewhere else by hand."
					}
				},
				{
					"name": "Trust an incoming key",
					"request": {
						"method": "POST",
						"header": [
							{
								"key": "username",
								"value": "{{username}}"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}"
							},
							{
								"key": "Content-Type",
								"value": "application/json"
							}
						],
						"body": {
							"mode": "raw",
							"raw": "{\n    \"pubkey\": \"ssh-ed25519 AAAA... vme-peer\",\n    \"label\": \"vme:10.0.0.10\"\n}",
							"options": {
								"raw": {
									"language": "json"
								}
							}
						},
						"url": {
							"raw": "{{url}}/peer/trust"
						},
						"description": "Answered *by* an appliance when another one pairs with it - normally called for you by `POST /peer/<id>/trust` on the sending appliance, not by hand."
					}
				}
			]
		},
		{
			"name": "system",
			"description": "Appliance version, licence information and logs.",
			"item": [
				{
					"name": "home",
					"request": {
						"method": "GET",
						"header": [],
						"url": {
							"raw": "{{url}}",
							"host": [
								"{{url}}"
							]
						},
						"description": "Returns the vME API version string. No authentication."
					},
					"response": []
				},
				{
					"name": "info",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/info",
							"host": [
								"{{url}}"
							],
							"path": [
								"info"
							]
						},
						"description": "Licence and appliance information (version, address, licence state)."
					},
					"response": []
				},
				{
					"name": "log/list",
					"protocolProfileBehavior": {
						"disableBodyPruning": true
					},
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/admin/log/list",
							"host": [
								"{{url}}"
							],
							"path": [
								"admin",
								"log",
								"list"
							]
						},
						"description": "Admin only. Reads one log file. Optional query: `limit`, `offset`."
					},
					"response": []
				},
				{
					"name": "log",
					"request": {
						"method": "GET",
						"header": [
							{
								"key": "username",
								"value": "{{username}}",
								"type": "text"
							},
							{
								"key": "api-key",
								"value": "{{api-key}}",
								"type": "text"
							}
						],
						"url": {
							"raw": "{{url}}/admin/log/vme-20260101",
							"host": [
								"{{url}}"
							],
							"path": [
								"admin",
								"log",
								"vme-20260101"
							]
						},
						"description": "Admin only. Reads one log file. Optional query: `limit`, `offset`."
					},
					"response": []
				}
			]
		}
	],
	"event": [
		{
			"listen": "prerequest",
			"script": {
				"type": "text/javascript",
				"requests": {},
				"exec": [
					""
				]
			}
		},
		{
			"listen": "test",
			"script": {
				"type": "text/javascript",
				"requests": {},
				"exec": [
					""
				]
			}
		}
	],
	"variable": [
		{
			"key": "url",
			"value": "https://your-vme-appliance/api"
		},
		{
			"key": "username",
			"value": ""
		},
		{
			"key": "api-key",
			"value": ""
		},
		{
			"key": "target_host",
			"value": ""
		},
		{
			"key": "source_portal",
			"value": ""
		},
		{
			"key": "target_portal",
			"value": ""
		},
		{
			"key": "target_username",
			"value": ""
		},
		{
			"key": "target_api_key",
			"value": ""
		},
		{
			"key": "client_address",
			"value": ""
		},
		{
			"key": "pool_name",
			"value": ""
		},
		{
			"key": "target_pool",
			"value": ""
		},
		{
			"key": "source_base",
			"value": "app01"
		},
		{
			"key": "snapshot_name",
			"value": "onboard-snap"
		},
		{
			"key": "template_id",
			"value": "sql_server_iscsi_one_volume"
		},
		{
			"key": "workflow_id",
			"value": ""
		},
		{
			"key": "source_agent_id",
			"value": ""
		},
		{
			"key": "target_agent_id",
			"value": ""
		},
		{
			"key": "job_id",
			"value": ""
		},
		{
			"key": "send_task_id",
			"value": ""
		},
		{
			"key": "peer_id",
			"value": ""
		},
		{
			"key": "peer_name",
			"value": "vme-nonprod-01"
		},
		{
			"key": "clone_base",
			"value": "app01_clone"
		},
		{
			"key": "source_iqn",
			"value": ""
		},
		{
			"key": "source_mount_id",
			"value": ""
		},
		{
			"key": "source_mount_root",
			"value": ""
		},
		{
			"key": "clone_iqn",
			"value": ""
		},
		{
			"key": "clone_mount_id",
			"value": ""
		},
		{
			"key": "target_mount_root",
			"value": ""
		},
		{
			"key": "snapshot_task_id",
			"value": ""
		},
		{
			"key": "task_id",
			"value": "",
			"type": "string"
		},
		{
			"key": "token_id",
			"value": "",
			"type": "string"
		},
		{
			"key": "licence_key",
			"value": "",
			"type": "string"
		}
	]
}
