Skip to content

Import & Export

VirtuProbe can export probes and entire bundles to JSON files, and import them back. This lets you share configurations between instances, commit them to version control, or add them to a Library collection.

Open the probe in the editor, click the export icon (↗) next to the probe name in the sidebar.

Click the export icon on a bundle in the sidebar. The browser downloads a .json file containing the bundle name and all its probes.

Click the import icon (↙) next to Add Probe in the sidebar toolbar and select a probe .json file. The probe is created inside the currently selected bundle.

Click the import icon next to Add Bundle and select a bundle .json file. A new bundle is created with all the probes from the file.

See Library — the Library import uses the same underlying format.


Import an API definition or request collection

Section titled “Import an API definition or request collection”

Already have your endpoints defined elsewhere? Bring them straight in. In the Bundles view, click Import Collection in the action toolbar and pick a format:

Import Collection dialog — format tabs for OpenAPI, Postman, Bruno, HAR, .http and Insomnia

FormatAcceptsResult
OpenAPI / SwaggerOpenAPI 3.x or Swagger 2.0, JSON or YAML — file, pasted text, or a URLOne HTTP probe per operation, grouped into sub-bundles by tag
PostmanPostman collection v2.1 export (.json) — file or pasted textRequests become probes; folders become sub-bundles
BrunoA single .bru request, or a .zip of the collection folderThe folder layout maps onto the bundle tree
HARAn HTTP Archive (.har) — file or pasted textOne probe per recorded request (identical requests de-duplicated)
.http / .restA request file using ### separators — file or pasted textOne probe per request
InsomniaAn Insomnia v4 export (.json) — file or pasted textRequests become probes; folders become sub-bundles

What gets mapped:

  • Method, URL, query/header parameters, and request body populate the probe. Path parameters and existing {{variables}} are preserved as placeholders; for OpenAPI the server URL is surfaced as {{baseUrl}} (define it in your environment).
  • Folders / tags become a nested bundle tree.
  • Authentication — Bearer, Basic, and API-key (header or query) schemes are mapped onto request headers/parameters. OAuth2 is not mapped yet; add the token header manually after import.

The import always creates a new bundle — it never overwrites an existing one. A malformed document is reported with a clear error and nothing is created.


All exported files use the same JSON structure. The type field distinguishes probes from bundles.

{
"vpVersion": 1,
"type": "probe",
"protocol": "HTTP",
"name": "My probe",
"description": "Optional description",
"tags": ["http", "rest"],
"data": { }
}
FieldTypeDescription
vpVersionintegerAlways 1
typestring"probe"
protocolstring"HTTP", "SMTP", "IMAP", "LDAP", "DNS", "SPAMD", "SMB"
namestringProbe display name
descriptionstring | nullOptional description
tagsstring[]Tag list, may be empty
dataobjectProtocol-specific payload — see below
{
"vpVersion": 1,
"type": "bundle",
"name": "My bundle",
"probes": [
{ "vpVersion": 1, "type": "probe", "protocol": "HTTP", ... }
]
}
{
"vpVersion": 1,
"type": "chain",
"name": "My chain",
"description": "Optional description",
"tags": ["http", "chain"],
"data": {
"name": "My chain",
"steps": [ ]
}
}

The data.steps array uses the same structure as the chain editor — see the chain steps reference.


{
"method": "GET",
"url": "https://example.com/api/resource",
"params": [
{ "enabled": true, "name": "key", "value": "val", "description": "" }
],
"headers": [
{ "enabled": true, "name": "Accept", "value": "application/json", "description": "" }
],
"cookies": [],
"body": null
}

method is one of GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.
body is a string or null. params, headers, cookies are arrays that may be empty.

{
"host": "localhost",
"port": 1025,
"ssl": false,
"commands": [
{ "enabled": true, "commandType": "EHLO", "data": "localhost", "expectedCode": 250 },
{ "enabled": true, "commandType": "MAIL_FROM", "data": "sender@example.com","expectedCode": 250 },
{ "enabled": true, "commandType": "RCPT_TO", "data": "to@example.com", "expectedCode": 250 },
{ "enabled": true, "commandType": "DATA", "data": null, "expectedCode": 354 },
{ "enabled": true, "commandType": "DATA_BODY", "data": "Subject: Hi\r\n\r\nBody text.", "expectedCode": null },
{ "enabled": true, "commandType": "QUIT", "data": null, "expectedCode": 221 }
]
}

Valid commandType values: EHLO, HELO, MAIL_FROM, RCPT_TO, DATA, DATA_BODY, QUIT, RSET, NOOP, VRFY, STARTTLS, AUTH, CUSTOM.
expectedCode is an integer assertion or null to skip. DATA_BODY sends the dot-stuffed message body; STARTTLS upgrades the connection.

{
"host": "localhost",
"port": 3143,
"ssl": false,
"commands": [
{ "enabled": true, "commandType": "LOGIN", "data": "username password", "expectedStatus": "OK" },
{ "enabled": true, "commandType": "SELECT", "data": "INBOX", "expectedStatus": "OK" },
{ "enabled": true, "commandType": "FETCH", "data": "1 (ENVELOPE)", "expectedStatus": "OK" },
{ "enabled": true, "commandType": "LOGOUT", "data": null, "expectedStatus": "OK" }
]
}

Valid commandType values: CAPABILITY, NOOP, LOGOUT, STARTTLS, LOGIN, AUTHENTICATE, SELECT, EXAMINE, CREATE, DELETE, RENAME, SUBSCRIBE, UNSUBSCRIBE, LIST, LSUB, STATUS, APPEND, CHECK, CLOSE, EXPUNGE, SEARCH, FETCH, STORE, COPY, MOVE, UID, CUSTOM.
expectedStatus is "OK", "NO", "BAD", or null to skip.

{
"host": "localhost",
"port": 389,
"ssl": false,
"commands": [
{
"enabled": true,
"commandType": "BIND",
"dn": "cn=admin,dc=example,dc=com",
"password": "secret",
"expectedResultCode": 0
},
{
"enabled": true,
"commandType": "SEARCH",
"dn": "dc=example,dc=com",
"filter": "(objectClass=inetOrgPerson)",
"scope": "SUB",
"attributes": "cn mail",
"sizeLimit": 0,
"timeLimit": 0,
"expectedResultCode": 0
},
{
"enabled": true,
"commandType": "UNBIND",
"expectedResultCode": null
}
]
}

Valid commandType values: BIND, SEARCH, UNBIND, DELETE, COMPARE.
scope is BASE, ONE, or SUB. attributes is a space-separated list; empty returns all.
expectedResultCode is an integer LDAP result code or null. Common codes: 0 success, 6 compareTrue, 49 invalidCredentials.

{
"host": "8.8.8.8",
"port": 53,
"udp": true,
"queries": [
{ "enabled": true, "name": "example.com", "type": "A", "recursionDesired": true, "expectedRcode": null }
]
}

Valid type values: A, AAAA, MX, CNAME, TXT, NS, PTR, SOA.
expectedRcode is an integer RCODE or null to skip. Common values: 0 NOERROR, 3 NXDOMAIN.
udp: true uses UDP (with automatic TCP retry on truncation); false forces TCP.

{
"host": "localhost",
"port": 783,
"command": "CHECK",
"version": "1.5",
"body": "From: user@example.com\r\nSubject: Hello\r\n\r\nMessage body."
}

Valid command values: PING, CHECK, SYMBOLS, REPORT, REPORT_IFSPAM, SKIP, PROCESS.

{
"host": "10.0.0.1",
"port": 445,
"dialect": "SMB2",
"authType": "NTLM",
"domain": "WORKGROUP",
"username": "smbuser",
"password": "Password123!",
"ntHash": "",
"signing": false,
"encryption": false,
"commands": [
{ "enabled": true, "commandType": "NEGOTIATE", "expectedStatus": null },
{ "enabled": true, "commandType": "SESSION_SETUP", "expectedStatus": null },
{ "enabled": true, "commandType": "TREE_CONNECT", "sharePath": "private", "expectedStatus": null },
{ "enabled": true, "commandType": "LIST_SHARES", "expectedStatus": null },
{ "enabled": true, "commandType": "TREE_DISCONNECT","expectedStatus": null },
{ "enabled": true, "commandType": "LOGOFF", "expectedStatus": null }
]
}

dialect is "SMB2" (default) or "SMB1". authType is "NONE", "NTLM", or "PTH" (pass-the-hash). For PTH, set ntHash to the 32-character hex NT hash and leave password empty.

Valid commandType values: NEGOTIATE, SESSION_SETUP, TREE_CONNECT, TREE_DISCONNECT, LOGOFF, ECHO, FILE_READ, FILE_WRITE, FILE_DELETE, FILE_RENAME, DIR_LIST, DIR_LIST_RECURSIVE, DIR_CREATE, DIR_REMOVE, LIST_SHARES, ACL_READ, ACL_WRITE.

expectedStatus is an NT status code integer (e.g. 0 for STATUS_SUCCESS) or null to skip the assertion. File operations use filePath or dirPath; FILE_WRITE also uses fileContent; FILE_RENAME uses newPath.


All string fields in data support {{variableName}} placeholders. At send time, placeholders are resolved from the active project environment. In chain steps, they are also resolved from the chain variable context produced by upstream extractors.