Docs

Request scripts

Open a request’s Scripts section to write JavaScript that runs before sending or after receiving a response. The Snippets menu and pm. completion list the available APIs.

Scripts run against a snapshot: their request edits affect that send without changing the request draft or saved file. An uncaught pre-request error prevents the request; a failed pm.test does not.

Collection scripts

Click a collection in the sidebar to open its tab. There you can rename it, edit the variables in its environment.toml, and write scripts that run for every request in the collection. Save with the Save button or the save shortcut.

In each phase the collection’s script runs first, then the request’s own script. Both scripts share pm.variables for that send. If the collection’s pre-request script fails, the request is not sent. If its post-response script fails, the request’s own tests still run. The tab stores the scripts in the collection’s .request-eagle-collection.toml.

Reuse a response value

pm.response.to.have.status(200);
pm.environment.set("token", pm.response.json().token);

Other requests in the same collection can then use Bearer {{token}}. Session values last until the workspace closes and are never written to environment.toml.

File values come from the collection’s environment.toml and from the global environment selected in the tab bar. The selected environment’s values take precedence. Global environments are stored in ~/.request-eagle/environments/<name>.toml.

Scripts read and change values in these scopes. A {{name}} reference uses the first one that has the name:

API Scope
pm.variables Overrides that last for the current execution only, or in the Collection Runner for the whole run.
pm.iterationData In the Collection Runner, the data file’s row for the iteration. It has get, has, unset, toObject and replaceIn.
pm.environment The selected environment, then the collection’s variables.
pm.collectionVariables The collection’s environment.toml.
pm.globals Values every collection shares. They start empty when the workspace opens.

Each scope has the same methods:

Method Behavior
get(name) / has(name) Read the file values plus session changes.
set(name, value) Set a value for the scope’s lifetime, converted to a string.
unset(name) / clear() Hide values for this session, including file values and those of the scopes below. pm.variables only removes its overrides.
toObject() / replaceIn(text) Copy the visible values, or substitute them in text.

Use {{!name}} to send a literal {{name}}.

Make HTTP calls from a script

const login = await pm.sendRequest({
    url: "{{base_url}}/login",
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({username: pm.environment.get("username")}),
});

login.to.have.status(200);
pm.environment.set("token", login.json().token);
pm.request.headers.upsert({key: "Authorization", value: "Bearer {{token}}"});

pm.sendRequest(url) sends GET. The response has code, status, responseTime, headers, text(), json(), and the same assertions as pm.response. HTTP 4xx/5xx statuses are normal responses; transport failures reject.

Subrequests use the primary request’s settings and do not run saved scripts. Like the primary request, they store and send cookies in the cookie jar, so a login subrequest’s session cookie goes with the request that follows. Timers, filesystem access, and fetch are not provided.

Read and change the body

pm.request.body.mode names the body’s type, as in Postman: raw, urlencoded, formdata or file.

API Body
pm.request.body.raw Raw text. Setting it, or calling update(text), makes any body raw text. After the response, it is what was sent.
pm.request.body.urlencoded A URL-encoded form’s fields: get, has, add, remove, upsert, clear and toJSON, like headers.
pm.request.body.formdata A multipart form’s parts, with the same methods. Text parts have a value; file parts have type: "file" and the file’s path in src.
pm.request.body.file.src The path of the file a binary body sends.

Sign and encode values

const body = pm.variables.replaceIn(pm.request.body.raw || "");
const signature = pm.crypto.hmacSha256(pm.environment.get("secret"), body);
pm.request.headers.upsert({key: "X-Signature", value: signature});
API Result
pm.crypto.sha256(text) SHA-256, lowercase hexadecimal.
pm.crypto.hmacSha256(secret, text) HMAC-SHA256, lowercase hexadecimal.
pm.crypto.randomBytes(count) Secure random bytes, hexadecimal.
pm.encoding.base64Encode(text) / .base64Decode(text) Standard padded Base64.
pm.encoding.base64UrlEncode(text) / .base64UrlDecode(text) URL-safe Base64 without padding.

Use Postman’s libraries

const CryptoJS = require("crypto-js");
const moment = require("moment");

const timestamp = moment().utc().format();
const signature = CryptoJS.HmacSHA256(timestamp, pm.environment.get("secret"));
pm.request.headers.upsert({key: "X-Timestamp", value: timestamp});
pm.request.headers.upsert({key: "X-Signature", value: CryptoJS.enc.Base64.stringify(signature)});

require loads these libraries, as Postman does:

Name Library
crypto-js crypto-js 4.2.0, also available as CryptoJS.
lodash Lodash 4.17.21, also available as _.
moment Moment.js 2.30.1.
uuid uuid() and uuid.v4() return a random UUID.
atob / btoa Base64 for text with one byte per character, also available as globals.

Other names throw an error.

Read and change cookies

pm.environment.set("session", pm.cookies.get("session"));

pm.cookies lists the cookies of the current exchange: those the request sends, from its Cookie header and the cookie jar, and after the response, with the response’s Set-Cookie headers applied. pm.response.cookies lists only the cookies the response set, with their attributes. Both have get(name), has(name), one(name), all(), count() and toObject().

pm.cookies.jar() reads and changes the cookie jar. As in Postman, its methods report through a callback:

const jar = pm.cookies.jar();
jar.set("https://api.example.com", "session", "abc", error => {
    if (error) throw error;
});
jar.get("https://api.example.com", "session", (error, value) => console.log(value));
Method Behavior
get(url, name, callback) The value of the cookie named name that a request to url sends.
getAll(url, callback) Every cookie a request to url sends, with its attributes.
set(url, name, value, callback) Keep a cookie as if a response from url set it. Instead of name and value, an object can also give path, domain, expires, maxAge, secure, httpOnly and sameSite.
unset(url, name, callback) Delete the cookies named name that a request to url sends.
clear(url, callback) Delete every cookie a request to url sends.

Changes made before sending apply to the request. When the cookie jar is off in Settings, pm.cookies lists only the cookies of the exchange and each jar method reports an error; without a callback, the error is logged.

Validate response structure

pm.test("Response matches the schema", () => {
    pm.response.to.have.jsonSchema({
        type: "object",
        required: ["id", "name"],
        properties: {
            id: {type: "integer"},
            name: {type: "string"},
        },
    });
});

For other values, pm.schema.validate(data, schema) returns {valid, errors, truncated}. The default dialect is Draft 2020-12. Local references such as #/$defs/user work; external references are not loaded.

Skip the primary request

if (!pm.environment.get("token")) {
    pm.execution.skipRequest("No access token configured");
}

The primary request and post-response script do not run.

In the Collection Runner, pm.execution.setNextRequest(name) and postman.setNextRequest(name) choose the request that runs next; a request sent on its own ignores them, as in Postman. The legacy postman object also has getEnvironmentVariable, setEnvironmentVariable, clearEnvironmentVariable, getGlobalVariable, setGlobalVariable and clearGlobalVariable.

Know where a script runs

pm.info describes the current execution:

Field Value
eventName prerequest or test, for a post-response script.
requestName / requestId The saved request’s name and ID.
iteration / iterationCount The Collection Runner’s iteration, counting from 0, and how many it runs. A request sent on its own runs iteration 0 of 1.
if (pm.info.iteration > 0) {
    pm.execution.skipRequest("Checked in the first iteration");
}

gRPC scripts

A gRPC request’s Scripts section has three scripts:

  • Before invoke runs before the method is invoked. It can change the server URL, metadata and message of that call, and pm.execution.skipRequest(reason) cancels it. It runs before server reflection loads the call’s methods, so it can also set the metadata that reflection needs.
  • On message runs for each message the server sends, in order.
  • After response runs once the server ends the call, including with an error status. It does not run when the call fails without a status, such as when the server is unreachable, or when you cancel it.

The three scripts share pm.variables during the call. A {{$guid}} or other generated value that Before invoke creates or sets keeps that value for the whole call, including stream messages. Collection scripts run only for HTTP requests.

// Before invoke
const auth = await pm.sendRequest({url: "{{base_url}}/login", method: "POST"});
pm.request.metadata.upsert({key: "authorization", value: "Bearer " + auth.json().token});
// On message
pm.test("Every update has an ID", () => {
    pm.expect(pm.message.data).to.have.property("id");
});
// After response
pm.test("Status is OK", () => pm.response.to.have.status("OK"));
pm.test("An update reports success", () => {
    pm.response.messages.to.include({status: "success"});
});
pm.environment.set("orderId", pm.response.messages.idx(0).data.id);

Messages appear as JSON, with lowerCamelCase field names and 64-bit integers as strings.

API Behavior
pm.request.url / .message The server and the composed message as text. Before invoke can assign them; an object assigned to message becomes JSON. Unary and server streaming methods send the message when invoked.
pm.request.methodPath The method as package.Service/Method.
pm.request.metadata get, has, add, remove, upsert, clear and toJSON, like headers. Keys are case-insensitive.
pm.message.data / .timestamp In On message, the received message and when it arrived.
pm.response.code / .status / .statusMessage In After response, the status code (0 is OK), its name such as NOT_FOUND, and the server’s message.
pm.response.responseTime Milliseconds from invoking until the status arrived.
pm.response.metadata / .trailers The metadata and trailers the server sent.
pm.response.messages / pm.request.messages In After response, the received and sent messages, each with data and timestamp.
pm.response.to.have.statusCode(code) / .status(codeOrName) Assert the status. pm.response.to.be.ok asserts OK, and .error any other status.
pm.response.to.have.metadata(key, value?) / .trailer(key, value?) Assert that the server sent a key, and optionally its value.
pm.response.to.have.message(object) Assert that a received message equals the object.

Message lists are arrays with idx(index), count(), all() and each(callback). Their filter also accepts the fields to match, such as filter({data: {type: "ping"}}).

Assertion Passes when
messages.to.include(fields) A message has these fields. Nested objects match the fields they name.
messages.to.not.include(fields) No message has these fields.
messages.to.have.property(path, value?) Every message has the property, such as user.id, optionally with this value. There must be a message.
messages.to.have.jsonSchema(schema) Every message matches the schema. There must be a message.

Limits

Each phase is limited to:

  • 2 seconds of active execution, 30 seconds elapsed, and a 32 MiB heap.
  • 32 HTTP calls with 4 in flight, 8 MiB per response and 16 MiB in total.
  • 500 tests and 500 console entries.
  • 1 MiB for crypto, Base64, and schema data, and 64 KiB for a schema.

On message runs once for each received message, with these limits for each run. A call shows up to 500 tests and 500 console entries from all of them. After response sees the latest 8 MiB of messages in each direction.