Pre-request and after-response scripts run locally in a sandbox. The canonical API object is poly. pm is a compatibility alias wrapping the same object, so pasted Postman scripts work as-is. Scripts are available on Free.
Open a request → Scripts tab. Two editors:
poly.sendRequest.token from JSON, assert status, log the body.Scripts are JavaScript. console.log / warn / error go to the IDE session console.
polyIn PolyApiIDE the canonical object name is poly, not pm. Write new scripts with poly.*.
pm is a compatibility alias wrapping the same object. Paste Postman scripts as-is — pm.environment.set and poly.environment.set mutate the same environment.
poly.sendRequest / pm.sendRequestThe call actually fires HTTP through the same Send stack as the IDE Send button (URL, auth, request cookies, proxy, variable substitution). It is not a stub and not a separate sandbox fetch: the network request leaves the extension because you ran the script.
Your script is never executed on PolyApiIDE servers.
The script is compiled locally with new Function on the extension sandbox page. The source does not go to polyapiclient.ru. That is Chrome Web Store compliant: no remote arbitrary code, no hidden network from the user script besides the Send stack.
Scripts are available on Free — no key required. QA scenarios, Collection Runner, load, AI and cloud backup stay on paid plans.
poly objectpoly.environment.get(name) / set(name, value) / unset(name) / has(name) / toObject() — active environment.poly.variables.get/set — current-scope variables (Postman-style pm.variables).poly.collectionVariables.get/set — collection variables.poly.globals.get/set — workspace globals.poly.test(name, fn) — assertion; the result is written to the session console.poly.response.json() / text() / code — after-response only.poly.cookies.get(name) — cookies stored on the request/collection (including after an explicit site cookie sync).The same methods exist on pm.
pm.sendRequestPre-request. You can paste this from Postman unchanged:
pm.sendRequest({
url: pm.environment.get("baseUrl") + "/login",
method: "POST",
header: { "Content-Type": "application/json" },
body: {
mode: "raw",
raw: JSON.stringify({
username: pm.environment.get("username"),
password: pm.environment.get("password")
})
}
}, function (err, res) {
if (err) {
console.log(err);
return;
}
const data = res.json();
pm.environment.set("token", data.token || data.access_token);
console.log("token updated");
});
poly.*poly.sendRequest({
url: poly.environment.get("baseUrl") + "/login",
method: "POST",
header: { "Content-Type": "application/json" },
body: {
mode: "raw",
raw: JSON.stringify({
username: poly.environment.get("username"),
password: poly.environment.get("password")
})
}
}, function (err, res) {
if (err) {
console.log(err);
return;
}
const data = res.json();
poly.environment.set("token", data.token || data.access_token);
console.log("token updated");
});
if (poly.response.code >= 200 && poly.response.code < 300) {
try {
const data = poly.response.json();
if (data.token || data.access_token) {
poly.environment.set("token", data.token || data.access_token);
console.log("token updated");
}
} catch (e) {
console.log("response is not JSON");
}
}
poly.test("status is 2xx", function () {
if (poly.response.code < 200 || poly.response.code >= 300) {
throw new Error("unexpected status " + poly.response.code);
}
});
In the IDE you can click Sync cookies from site — that is an explicit UI action, not a script. After sync, values land in request cookies and are available to helpers:
const sid = poly.cookies.get("sessionid");
console.log("sessionid", sid);
The optional cookies permission is requested on click and scoped to the request URL hostname. Details are in the privacy policy.