Skip to content

Migrating from Postman

When you import a Postman collection, HarborClient copies pre-request and post-request script text into the collection and request settings verbatim as one inline script per request stage. Postman scripts use the global pm object; HarborClient scripts use hc. There is no pm compatibility layer — any pm.* reference throws pm is not defined at runtime.

After import, open each script and rewrite it against the hc API described above. You can split a long imported script into multiple list entries or replace repeated blocks with snippets. The sections below map common Postman patterns to HarborClient equivalents and call out features that have no direct replacement.

pm to hc API mapping

Postman (pm)HarborClient (hc)Notes
pm.variables.get(key) / pm.variables.set(key, value)hc.request.variables.get(key) / hc.request.variables.set(key, value)Session-only; not persisted after the send
pm.variables.unset(key)hc.request.variables.clear(key)Session-only clear
pm.variables.replaceIn(template)hc.request.variables.replaceIn(template)Resolves {{key}}, runtime vars, and dynamic {{$name}} tokens
pm.environment.get(key) / pm.environment.set(key, value)hc.environment.variables.get(key) / hc.environment.variables.set(key, value)Persists to the active environment when one is selected
pm.environment.unset(key)hc.environment.variables.clear(key)Removes key from active environment after send
pm.collectionVariables.get(key) / pm.collectionVariables.set(key, value)hc.collection.variables.get(key) / hc.collection.variables.set(key, value)Persists to the collection after the send
pm.collectionVariables.unset(key)hc.collection.variables.clear(key)Removes key from collection after send
pm.globals.get(key) / pm.globals.set(key, value)hc.globals.get(key) / hc.globals.set(key, value)Persists to app global variables after the send
pm.globals.unset(key)hc.globals.clear(key)Removes key from globals after send
postman.setEnvironmentVariable(key, value)hc.environment.variables.set(key, value)Legacy Postman alias
postman.setGlobalVariable(key, value)hc.globals.set(key, value)Legacy Postman alias; persists to globals after the send
pm.cookies.get(name) / pm.cookies.set(name, value)hc.cookies.get(name) / hc.cookies.set(name, value)Scoped to request host at send start; persists to cookie jar
pm.cookies.unset(name) / pm.cookies.clear(name)hc.cookies.clear(name)Removes cookie for request host after send
pm.sendRequest(options, callback)await hc.fetch(url, { method, headers, body })Opt-in via Settings → General; native fetch signature; async/await, not callbacks
(no Postman equivalent)await hc.send(text, status?) / await hc.sendJSON(value, status?)Synthetic response override; pair with skipRequest to mock
(no Postman equivalent)await hc.fs.readText(path) / await hc.fs.writeText(path, text) / …HarborClient-specific; opt-in file read/write under script root
(no Postman equivalent)await hc.parse.yaml(text) / await hc.stringify.csv(rows)HarborClient-specific in-memory YAML/CSV codecs
pm.execution.setNextRequest(name) / pm.execution.setNextRequest(null)hc.execution.setNextRequest(name) / hc.execution.setNextRequest(null)Collection runner only; null stops the run
pm.execution.skipRequest()hc.execution.skipRequest()Skips HTTP send; runner marks step Skipped
(no Postman equivalent)hc.execution.workflowNextAction(actionId)Workflow playback only; jumps by action UUID
(no Postman equivalent)hc.execution.workflowSkipAction()Workflow playback only; skips action (and HTTP in pre)
pm.info.eventNamehc.info.eventName"prerequest" or "test"
pm.info.requestNamehc.info.requestNameSaved request display name
pm.info.requestIdhc.info.requestIdSaved id as string; empty when unsaved
pm.info.iterationhc.info.iteration0 unless data-driven collection iterations are supported
(no Postman equivalent)hc.info.workflowId / workflowActionId / workflowActionIterationEmpty / -1 outside workflow playback
(no Postman equivalent)hc.info.livepageIdLive page UUID; empty outside a linked live page
(no Postman equivalent)hc.info.liveserverIdSaved live server id; empty outside a live-server script run
pm.request.methodhc.request.methodGet/set
pm.request.urlhc.request.urlGet/set
pm.request.body (raw mode)hc.request.bodyGet/set as text
pm.request.headers.get(key)hc.request.headers.get(key)Case-insensitive
pm.request.headers.add({ key, value }) / pm.request.headers.upsert({ key, value })hc.request.headers.set(key, value) or hc.request.headers.set({ key: value })Batch or single upsert
pm.request.headers.toObject()hc.request.headers.get()No-arg get() returns a plain object
pm.request.url.getQueryString() / query param helpershc.request.params.get() / get(key) / set() / clear()Parameter bag over query params; current send only
pm.request.auth (Bearer / Basic helpers)hc.request.auth.get() / set() / update()Flat auth object; merges on set; current send only
pm.response.codehc.response.codeHTTP status code (e.g. 200)
pm.response.statushc.response.statusStatus text (e.g. OK)
pm.response.text()hc.response.text()Response body as string
pm.response.json()hc.response.json()Parses JSON; throws on invalid JSON
pm.response.responseTimehc.response.responseTimeRound-trip time in milliseconds
pm.response.headers.get(name)hc.response.headers[name]Flat read-only map; use bracket notation, not .get()
Cheerio $('selector') / HTML DOM helpershc.response.document().querySelector('selector')CSS selectors only; returns a thin facade, not Cheerio $()
pm.test(name, fn)hc.test(name, fn)Same pattern
pm.expect(actual).to.equal(expected)hc.expect(actual).to.equal(expected)Strict equality
pm.expect(actual).to.eql(expected)hc.expect(actual).to.eql(expected)Deep equality (Chai)
pm.expect(actual).to.include(substr)hc.expect(actual).to.include(substr)String, array, or object contains
pm.expect(actual).to.be.okhc.expect(actual).to.be.okTruthy check
pm.response.to.have.status(200)hc.response.to.have.status(200)Postman-style response matcher
pm.response.to.have.header("Content-Type", "application/json")hc.response.to.have.header("content-type", "application/json")Header names are case-insensitive
pm.response.to.be.jsonhc.response.to.be.jsonContent-Type includes JSON and body parses
pm.response.to.have.jsonBody({ ok: true })hc.response.to.have.jsonBody({ ok: true })Deep equality on parsed JSON
pm.response.to.be.ok / pm.response.to.be.successhc.response.to.be.ok / hc.response.to.be.success2xx status
pm.response.to.be.clientError / pm.response.to.be.notFoundhc.response.to.be.clientError / hc.response.to.be.notFoundStatus-class shortcuts

Collection-level headers in Postman are usually set in the collection UI. In HarborClient, use hc.collection.headers.set(key, value) in a script or configure headers in collection settings. See hc.collection.headers above.

Collection-level auth in Postman is configured in the collection Authorization tab. In HarborClient, use hc.collection.auth.set() / update() in a script or configure auth in Collection Settings — Authorization. Collection auth changes from scripts persist after the send completes.

Not supported

These Postman script features have no HarborClient equivalent:

  • require(...) / Postman bundled libraries — lodash, crypto-js, ajv, and other Postman built-ins and pm.require('npm:…') packages are not available. HTML querying is built in via hc.response.document(); npm package imports are not supported yet. To share your own code, use snippet imports or Select snippet… instead of copying blocks into every script.
  • pm.response.to.* matchers not listed in the migration table — HarborClient supports the common subset under hc.response.to. Not included: jsonSchema (requires ajv), JSON-path jsonBody(path, value), and response-size/time-specific matchers (use hc.expect on hc.response.responseTime or body length instead).
  • pm.iterationData, visualizers, and the legacy tests["name"] = true global.
  • Request body type on the active request — scripts cannot switch between JSON, form, and multipart body modes on the request being sent; only hc.request.body text is writable. Put query parameters on the URL passed to hc.fetch; set Content-Type via init.headers when sending a body.
  • pm.sendRequest callbacks — HarborClient uses await hc.fetch(...) instead of Node-style callbacks.

pm.sendRequest is supported when Allow script network requests is enabled — see hc.fetch. It does not run collection or request authorization automatically; pass headers or tokens explicitly in the fetch init object.

Modern JavaScript syntax (const, arrow functions, template literals, optional chaining, top-level await, and similar) is supported in migrated scripts. Relative snippet imports (import … from './name.js') are supported; Postman require, npm packages, and bundled libraries are not — see Sandbox limits and Importing snippets.

Example: rewrite a Postman test script

Postman post-request script:

javascript
var jsonData = pm.response.json();
pm.environment.set("token", jsonData.token);

pm.test("Status code is 200", function () {
  pm.response.to.have.status(200);
});

pm.test("Content-Type is JSON", function () {
  pm.expect(pm.response.headers.get("Content-Type")).to.include(
    "application/json"
  );
});

Equivalent HarborClient post-request script:

javascript
var jsonData = hc.response.json();
hc.environment.variables.set("token", jsonData.token);

hc.test("Status code is 200", function () {
  hc.response.to.have.status(200);
});

hc.test("Content-Type is JSON", function () {
  hc.response.to.have.header("content-type", "application/json");
});

Example: rewrite an HTML test script

Postman post-request script (Cheerio in the sandbox):

javascript
pm.test("Page has heading", function () {
  pm.expect($("h1").text()).to.include("Welcome");
});

Equivalent HarborClient post-request script:

javascript
hc.test("Page has heading", function () {
  var heading = hc.response.document().querySelector("h1");
  hc.expect(heading?.textContent).to.include("Welcome");
});

For collection import behavior and other Postman feature gaps, see Collections — Postman collections.