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.eventName | hc.info.eventName | "prerequest" or "test" |
pm.info.requestName | hc.info.requestName | Saved request display name |
pm.info.requestId | hc.info.requestId | Saved id as string; empty when unsaved |
pm.info.iteration | hc.info.iteration | 0 unless data-driven collection iterations are supported |
| (no Postman equivalent) | hc.info.workflowId / workflowActionId / workflowActionIteration | Empty / -1 outside workflow playback |
| (no Postman equivalent) | hc.info.livepageId | Live page UUID; empty outside a linked live page |
| (no Postman equivalent) | hc.info.liveserverId | Saved live server id; empty outside a live-server script run |
pm.request.method | hc.request.method | Get/set |
pm.request.url | hc.request.url | Get/set |
pm.request.body (raw mode) | hc.request.body | Get/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 helpers | hc.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.code | hc.response.code | HTTP status code (e.g. 200) |
pm.response.status | hc.response.status | Status 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.responseTime | hc.response.responseTime | Round-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 helpers | hc.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.ok | hc.expect(actual).to.be.ok | Truthy 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.json | hc.response.to.be.json | Content-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.success | hc.response.to.be.ok / hc.response.to.be.success | 2xx status |
pm.response.to.be.clientError / pm.response.to.be.notFound | hc.response.to.be.clientError / hc.response.to.be.notFound | Status-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 andpm.require('npm:…')packages are not available. HTML querying is built in viahc.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 underhc.response.to. Not included:jsonSchema(requires ajv), JSON-pathjsonBody(path, value), and response-size/time-specific matchers (usehc.expectonhc.response.responseTimeor body length instead).pm.iterationData, visualizers, and the legacytests["name"] = trueglobal.- 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.bodytext is writable. Put query parameters on the URL passed tohc.fetch; setContent-Typeviainit.headerswhen sending a body. pm.sendRequestcallbacks — HarborClient usesawait 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:
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:
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):
pm.test("Page has heading", function () {
pm.expect($("h1").text()).to.include("Welcome");
});Equivalent HarborClient post-request script:
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.
