Hook uses a JavaScript engine (QuickJS, ES2023) for pre-request, pre-auth, and post-request scripts. Scripts have full access to modern JavaScript: arrow functions, const/let, template literals, destructuring, async/await, Promises, and more.
Scripts are defined per-request in the Scripts tab. Each script has Load, Save, and Clear buttons. Scripts can also be embedded in collection JSON via the pre_script, pre_auth_script, and post_script fields.
All Hook-specific functionality is accessed through the global
hk object.
Properties (read/write in pre-request, read-only in post-request):
hk.request.url // request URL string
hk.request.method // HTTP method string
hk.request.body // request body string
hk.request.bodyType // body type (0=none, 1=raw, 2=json, 3=form, 4=graphql, 5=multipart)
hk.request.headers // all headers as {name: value} object
Methods:
hk.request.getHeader("name") // get a header value
hk.request.setHeader("name", "value") // add or overwrite a header
hk.request.removeHeader("name") // remove a header
hk.request.getHeaders() // get all headers as object
Properties:
hk.response.status // HTTP status code (number)
hk.response.statusText // status text (e.g. "OK")
hk.response.body // raw response body string
hk.response.time // elapsed time in milliseconds
hk.response.size // response body size in bytes
hk.response.headers // all headers as {name: value} object
Methods:
hk.response.json() // parse body as JSON
hk.response.text() // alias for .body
hk.response.getHeader("name") // get a response header
hk.response.getHeaders() // get all headers as object
In pre-request scripts, hk.response is
undefined.
hk.env.get("key") // get environment variable value
hk.env.set("key", "value") // set environment variable
hk.env.has("key") // check if variable exists (boolean)
hk.env.unset("key") // remove variable
hk.env.toObject() // all variables as {key: value} object
Variables set via hk.env.set() are available in
subsequent template expansions within the same session. They do not
modify the environment JSON file on disk.
hk.log("request starting")
Prints a message to the activity log. The message appears in the Log
tab prefixed with [script].
console.log("debug info", someObject)
console.warn("potential issue")
console.error("something failed")
Standard console methods that output to the activity log. Multiple arguments are space-separated. Objects are stringified. The activity-log tag indicates the level:
[script] debug info {key: "value"}
[script] warn: potential issue
[script error] something failed
Uncaught JavaScript exceptions also surface under
[script error].
Defines a named test block. If the function throws, the test fails.
hk.test("Status code is 200", () => {
hk.expect(hk.response.status).toBe(200);
});
hk.test("Body contains user", () => {
const data = hk.response.json();
hk.expect(data.name).toBe("Alice");
hk.expect(data.items).toHaveLength(3);
});
Results appear in the Log tab:
[script] [test] PASS: Status code is 200
[script] [test] FAIL: Body contains user - toBe: expected "Alice" but got "Bob"
Returns an assertion chain. Available matchers:
hk.expect(value).toBe(expected) // strict ===
hk.expect(value).toEqual(expected) // deep equality
hk.expect(value).toContain(substring) // string includes or array includes
hk.expect(value).toBeGreaterThan(n) // value > n
hk.expect(value).toBeLessThan(n) // value < n
hk.expect(value).toBeTruthy() // !!value
hk.expect(value).toBeFalsy() // !value
hk.expect(value).toBeNull() // === null
hk.expect(value).toBeUndefined() // === undefined
hk.expect(value).toHaveProperty("key") // key in value
hk.expect(value).toHaveLength(n) // value.length === n
hk.expect(value).toMatch(/regex/) // regex test
hk.expect(hk.response.status).not.toBe(500);
hk.expect(hk.response.body).not.toContain("error");
hk.request.setHeader("X-Client", "hook-app");
hk.request.setHeader("X-Timestamp", new Date().toISOString());
const token = hk.env.get("api_token");
if (token) {
hk.request.setHeader("Authorization", `Bearer ${token}`);
}
const secret = hk.env.get("hmac_secret");
if (secret) {
hk.request.setHeader("X-Auth-Source", "script");
}
hk.test("Status is 200", () => {
hk.expect(hk.response.status).toBe(200);
});
hk.test("Response time under 500ms", () => {
hk.expect(hk.response.time).toBeLessThan(500);
});
hk.test("Body has expected shape", () => {
const data = hk.response.json();
hk.expect(data).toHaveProperty("id");
hk.expect(data).toHaveProperty("name");
hk.expect(data.items).toHaveLength(3);
});
// Extract token for next request
const data = hk.response.json();
if (data.access_token) {
hk.env.set("api_token", data.access_token);
}
console.log("Status:", hk.response.status);
console.log("Content-Type:", hk.response.getHeader("Content-Type"));
console.log("Time:", hk.response.time, "ms");
Hook includes script converters in the Import Datas popup:
The converter handles the most common API calls:
| Postman | Bruno | Hook |
|---|---|---|
pm.environment.get("k") |
bru.getEnvVar("k") |
hk.env.get("k") |
pm.environment.set("k",v) |
bru.setEnvVar("k",v) |
hk.env.set("k",v) |
pm.response.code |
res.getStatus() |
hk.response.status |
pm.response.json() |
res.getBody() |
hk.response.json() |
pm.request.url |
req.getUrl() |
hk.request.url |
pm.test("n", fn) |
test("n", fn) |
hk.test("n", fn) |
pm.expect(v) |
expect(v) |
hk.expect(v) |
Unsupported calls are commented out with // TODO:
markers.
Scripts are stored as plain JavaScript. The Scripts tab accepts
.hook and .js file extensions via the
Load/Save buttons. Scripts are saved in the scripts/
directory.
hk.test() blocks are caught
per-test (logged as FAIL, other tests continue).hk.test() blocks stop the script
and log the error message.