Function Reference
A complete catalogue of PruTAN's ~130 built-in fn.* functions (sections 1–11), grouped by how they are used in real testing work — synthetic data generation, payments/banking data, verification, transformation, and payment-security (HSM). Sections 12–14 cover the sibling binding objects available in the same scripts and rules — JWE/MAC on the message object, EMV chip cryptograms (emv), and script memory (ctx).
For an introduction to what functions are and how they resolve, see Functions. Example outputs below are illustrative; values are randomized on every run.
- In a request body, call a function as
{{$functionName(args)}}. - In a script or rule (Pre-request Script, Sandbox / Interceptor rules), call it as
fn.functionName(args). - Arguments may be quoted or unquoted; quoting (
fn.generateCard("12","3")) is the safe habit. emv.*,ctx.*, and the message object's own methods (req.jweEncrypt(...),res.stampMAC(...)) don't take thefn.prefix — see sections 12–14.
1. Identity & User Data
For seeding realistic, PII-free user records in API and onboarding tests.
| Function | Example output | Notes |
|---|---|---|
randomFirstName() | Noah | |
randomLastName() | Johnson | |
randomFullName() | Liam Jones | |
randomNamePrefix() | Dr. | |
randomNameSuffix() | PhD | |
randomUserName() | Jarrell.Gutkowski | |
randomEmail() | 4bwh7gg4g@sample.com | Random domain |
randomExampleEmail() | Kerluke73@example.com | Safe @example.* domain |
randomPhoneNumber() | 706-172-6732 | |
randomPhoneNumberExt() | 85-301-355-9096 | With extension |
generateRandomMobileNumber() | 6489132104 | 10-digit mobile |
2. Finance & Payments
The core set for card, ISO 8583 and UPI/bank testing.
| Function | Example output | Notes |
|---|---|---|
generateCard() | 8763310510066981 | 16-digit default |
generateCard(10) | 6740787467 | Length only |
generateCard(12, 3) | 365941689603 | Length + BIN |
generateAmount() | 11378 | 5-digit default |
generateAmount(3) | 920 | Integer amount |
generateAmount(4, 2) | 5675.92 | Digits + decimals |
generateCountryCode("india") | 356 | Any case works (india/INDIA/India) |
generateCurrencyCode("india") | INR | Any case works |
generateRandomIFSC() | BARB08863827 | Indian bank IFSC |
generateUPIAddress() | y1iykwe@axisbank | Random handle |
generateUPIAddress("hdfc") | mw1wn6ur4@hdfcbank | Bank hint |
randomBankAccount() | 22293803 | |
randomBankAccountBic() | ZZBHCA4J2WR | SWIFT/BIC |
randomBankAccountIban() | YF76CQVWIE1YMYQO68GLRE3SQDAVM33 | IBAN |
randomBankAccountName() | Business Account | |
randomCreditCardMask() | 4765 | Last-4 mask |
randomBitcoin() | 1Whyzk53g4cTZvxamzvAyBb7k8arg | BTC address |
randomCurrencyCode() | IDR | ISO 4217 code |
randomCurrencyName() | Danish Krone | |
randomCurrencySymbol() | ₸ | |
randomTransactionType() | Purchase |
3. Geo & Location
| Function | Example output |
|---|---|
randomCity() | Greenville |
randomCountry() | Austria |
randomCountryCode() | US |
randomLatitude() | 61.25626319907147 |
randomLongitude() | -105.95563595525634 |
randomStreetAddress() | 83152 General Street |
randomStreetName() | Kuhic Island |
4. Internet, System & Tech
| Function | Example output |
|---|---|
randomIP() | 158.42.179.24 |
randomIPV6() | 9dca:9b16:8990:c41b:efde:120a:482f:c87f |
randomMACAddress() | 6c:36:eb:e0:76:90 |
randomUUID() / guid() | 84896dba-d93d-47f7-9354-55f2dcdf1115 |
randomUserAgent() | Mozilla/5.0 (Windows NT 10.0; …) |
randomProtocol() | http |
randomSemver() | 9.6.4 |
randomPassword() | j8FdufH2dpuVf3x |
randomDomainName() | gracie.biz |
randomDomainSuffix() | info |
randomDomainWord() | donnell |
randomUrl() | https://portal.co |
randomLocale() | bm |
getRandomOS() | Windows 10 |
randomDatabaseCollation() | utf8_general_ci |
randomDatabaseColumn() | status |
randomDatabaseEngine() | CSV |
randomDatabaseType() | blob |
5. Business & Company
| Function | Example output |
|---|---|
randomCompanyName() | Walker and Sons |
randomCompanySuffix() | Inc |
randomJobArea() | Support |
randomJobDescriptor() | Dynamic |
randomJobTitle() | Chief Configuration Manager |
randomJobType() | Engineer |
randomBs() | synergize scalable platforms |
randomBsAdjective() | agile |
randomBsBuzz() | synergize |
randomBsNoun() | platforms |
randomCatchPhrase() | Seamlessly integrated modular system |
randomCatchPhraseAdjective() | Business-focused |
randomCatchPhraseDescriptor() | needs-based |
randomCatchPhraseNoun() | framework |
6. Images
All return a URL (or data URI) — useful for profile / catalogue fields.
randomAbstractImage(), randomAnimalsImage(), randomAvatarImage(), randomBusinessImage(), randomCatsImage(), randomCityImage(), randomFashionImage(), randomFoodImage(), randomNatureImage(), randomNightlifeImage(), randomPeopleImage(), randomSportsImage(), randomTransportImage(), randomImageUrl(), randomImageDataUri().
randomAvatarImage() → https://s3.amazonaws.com/uifaces/faces/twitter/…/128.jpg
randomImageUrl() → https://picsum.photos/640/480/7. Text & Miscellaneous
| Function | Example output | Notes |
|---|---|---|
randomAbbreviation() | HTML | |
randomAlphaNumeric() | 3 | Single char |
generateAlphaNumeric(9) | sMv5tLO7A | Fixed length |
generateAlphabet(7) | fYyvKrB | Letters only |
generateAlphabet() | DTeAbKzb | No-arg → 8 chars |
generateRandomNumber(6) | 945008 | Fixed length |
generateRandomNumber() | 478212 | No-arg → 6 digits |
randomBoolean() | false | See boolean note below |
randomColor() | purple | |
randomHexColor() | #566bf7 | |
randomInt() | 995 |
8. Date & Time
| Function | Example output | Notes |
|---|---|---|
generateDate("yyyy-MM-dd HH:mm:ss") | 2026-09-10 06:57:28 | Format tokens + -1days / +1months offsets — see Functions |
isPastDate("26-09-2025 06:30:00", "dd-MM-yyyy HH:mm:ss") | true | Verification — is the date in the past |
randomDateFuture() | 2027-02-10T06:57:28 | |
randomDatePast() | 2025-07-07T06:57:28 | |
randomDateRecent() | 2026-07-16T06:57:28 | |
randomMonth() | April | |
randomWeekday() | Monday | |
timestamp() | 1786431448 | Unix epoch (seconds) |
isoTimestamp() | 2026-08-11T06:57:28.025Z | ISO-8601 |
9. Verification & Validation
Return a boolean — use them in if() conditions and validation rules.
| Function | Example | Purpose |
|---|---|---|
startsWith("Bearer", "Bearer abc.def") | true | Prefix check (e.g. auth header) |
compare("original", "original") | true | Equality check |
match("\\bworld\\b", "Hello world") | true | Regex match |
isPastDate(date, format) | true | Date is in the past |
typeOf("1234", "number") | false | Type assertion |
// use directly in a rule condition
if(fn.startsWith(req.getHeader("Authorization"), "Bearer")) {
res.setBody("authScheme", "bearer");
}10. Transformation & Utility
| Function | Example | Purpose |
|---|---|---|
concatenate("Johnm", "Doe") | JohnmDoe | Join values (variadic) |
subString("HelloWorld", "2", "5") | lloWo | Slice by index |
length("Hello World") | 11 | Length of string or array (length([a,b,c,d,e]) → 5) |
size([1,2,3]) | 3 | Array size (also accepts a stringified array) |
toString(1434.92) | 1434.92 | Number → string |
stringify({"id":1,"name":"John"}) | {"id":1,"name":"John"} | Object → JSON string |
parseJson('{"id":1}') | {"id":1} | JSON string → object/array. Throws if the string isn't valid JSON. |
guid() | ff463c05-8be8-4cab-9c40-4a3dfd9e634b | UUID v4 |
sleep(1500) | 1500 | Pauses this rule for that many milliseconds, then continues. Returns the number of milliseconds it actually slept. The pause is capped at 10 s (the executor setting RULE_SLEEP_MAX_MS). A bigger value is cut down to the cap. In a Sandbox or Interceptor rule, the pause holds only that one connection. Stress Lab runs no rules, so it never applies there. |
11. Payment Security — HSM, PIN & Crypto
Advanced payment functions that operate against a Key Management entry (Certificate & Key Management). Pass the entry name (e.g. "API Keys") — not raw key bytes.
"API Keys"?"API Keys" is simply the name of a Key Management entry in Certificate & Key Management that stores the working keys (PEK / MAK / TEK). The HSM and PIN functions take that entry name and look up the stored keys internally — so you never paste raw key material into a rule. Create your own entry (any name works), add the required keys, then pass that name to the function. In these examples the entry happens to be named "API Keys".Not to be confused with the API Keys feature (CI/CD authentication tokens) — unrelated, despite the similar name.Related pages: Certificate & Key Management · Crypto · EMV Function
format below is the ISO 9564 PIN block format number: 0/1/3 for 3DES keys, 4 for AES keys — must match the entry's saved key Mode.
| Function | Example | Purpose |
|---|---|---|
generatePinBlock("1234", "4111111111111111", "0", "API Keys") | 2OAfNMxXF0y8o8LM8LaLXQ== (hex) | Build a PIN block under the entry's PEK |
verifyPinBlock(block, "1234", "4111111111111111", "0", "API Keys") | true | Verify a PIN block |
translatePinBlock(block, "4111111111111111", "0", "API Keys", "0", "API Keys") | 2OAfNMxXF0… | Re-encipher under another key/format |
encryptPin("1234", key) / decryptPin(enc, key) | … / 1234 | PIN encrypt / decrypt |
getPEK("API Keys") / getMAK / getTEK / getKEK / getIMK | A0EA903BE63A0FD0… | Read the PIN / MAC / TEK / KEK / IMK key |
setPEK("API Keys", "<hex>") / setMAK / setTEK / setKEK / setIMK | — | Set a key on the entry |
decryptTR31KeyBlock(block, "API Keys") | <hex key><KCV> | Unwrap a TR-31 key block under the entry's KEK — see TR-31 key exchange |
generateEmvDates() | — | Not implemented yet — always returns nothing. Do not use. |
generateTMK(...) / generateTPK(...) | — | Master / PIN key generation (needs real key material) |
For general (non-PIN) encryption use encrypt / decrypt with a certificate key — see Crypto.
12. Message Security — JWE & MAC
These live on the message object (req/res/ireq/ires), not on fn — a stamp or a JWE covers the whole message, and an interceptor has four messages in flight, so there's no single implicit target for fn to write to.
JWE (RFC 7516) — encrypt/decrypt against a stored certificate or a shared key:
| Function | Purpose |
|---|---|
req.jweEncrypt(text, "certName", header?, secrets?) | Encrypt text/object into a compact JWE. Default RSA-OAEP-256 + A256GCM; header overrides alg/enc/kid. |
req.jweDecrypt(text, "certName") | Decrypt a compact JWE back to text — algorithm is read from the token's own header |
req.jweVerify(text, "certName") | true/false — does it decrypt cleanly. Never throws. |
req.jweHeader(text) | The token's header (alg, enc, kid, …) read without decrypting — no key needed |
req.jweTrace() | Every step of the last jweEncrypt/jweDecrypt/jweVerify on this message, for print() |
res.setBody("token", req.jweEncrypt(req.getBody("card"), "PartnerCert"));MAC — ISO messages only, needs an ISO spec/key service wired into the run:
| Function | Purpose |
|---|---|
req.generateMAC("API Keys", fieldKey?, includeHeader?) | Compute the stamp as hex; the script places it. fieldKey defaults to DE128 when a field above 64 is used, else DE64. |
req.stampMAC("API Keys", fieldKey?, includeHeader?) | generateMAC + write it into that field in one call — the one function here that writes to the message |
req.verifyMAC("API Keys", fieldKey?, includeHeader?) | true/false — does the stamp already in the message match a fresh one |
req.macTrace() | Shows what went into the last MAC this script made: each part, the whole input (hex and text) and the MAC. It never shows the key. |
res.stampMAC("API Keys"); // computes DE64 (or DE128) and writes it inMAC over selected fields. Some switches (FSS, for example) make the MAC from only some fields and put it in a field of their own. To do this, pass a settings map instead of fieldKey:
req.stampMAC("FSS Keys", { fields: [2, 3, 4, 7, 11, 37, 41], into: "126.10" });
print(req.macTrace());Only the listed fields go into the MAC, in the order you list them. The MAC goes into into. That can be any field or subfield, and it is not part of the MAC itself. generateMAC and verifyMAC take the same map. Write a subfield as text, for example "126.10". Written as a number, 126.10 would read as 126.1.
| Setting | What it does | Default |
|---|---|---|
fields | The fields that go into the MAC, in this order | required |
into | The field the MAC goes into | DE64, or DE128 above field 64 |
mti | Put the message type (MTI) first | no |
lengths | Include each field's length prefix, as it is sent | no |
text | Use each value's characters instead of the bytes as sent. Useful when the spec packs numbers as BCD. | no |
separator | Text put between fields, for example " " | none |
missing | A listed field that is not in the message: "skip" it, or "error". A field that is there but empty still counts as there. | "skip" |
padding | 3DES only: "zero" or "iso2" | "zero" |
width | MAC length in bytes | the into field's fixed size, else 8 |
If you don't know a host's exact rule, try the settings and compare req.macTrace() with the host's log until the input matches. If a part holds a card secret (PIN, CVV, iCVV or CVV2), macTrace() hides that part.
A map without fields makes the usual whole-message MAC. For example, { into: "128", header: true } is the same as "128", true.
13. EMV Chip Cryptograms — ARQC/ARPC
The emv binding builds and checks EMV chip cryptograms (CVN 10/18/22 Visa, 16/17/18/20/21 Mastercard). Every call takes a plain data map and returns a value — nothing here writes into a message, not even parseChip, which only reads one.
Key names resolve against a Key Management entry's IMK box — the same entries as section 11, different box.
| Function | Purpose |
|---|---|
emv.parseChip(tlvHex, source?) | Parse EMV TLV (e.g. field 55) into a data map |
emv.generateArqc({key, profile, data}) | The chip's one-time stamp — returns it, the script places it (e.g. tag 9F26) |
emv.verifyArqc({key, profile, data, arqc}) | Recompute the ARQC and compare it to the one that arrived |
emv.generateArpc({key, profile, data, arqc, arc|csu}) | The bank's reply cryptogram for an ARQC that arrived |
emv.verifyArpc({..., arpc}) | Recompute the expected reply cryptogram and compare (prefix match — issuer data may follow it on the wire) |
emv.nextAtc(cardKey) | Advance and return this card's saved ATC counter (tag 9F36) — persists via the environment, wraps at 65535 |
emv.trace() | Every step of the last chip calculation, for print() |
chip = emv.parseChip(req.getBody("55"));
arqc = emv.generateArqc({key: "chip_imk", profile: "visa18", data: chip});
req.setEMVTagValue("55", "9F26", arqc);14. Script Memory — ctx
ctx isn't a generator — it's a plain per-test-run scratch space. A Pre-request Script and the Validation/Rules step normally get a brand-new, empty set of bindings each; ctx is the one object that's the same dict across both, for one test run. It does not survive between separate runs — for that, use the environment (the way emv.nextAtc does).
| Function | Purpose |
|---|---|
ctx.set(key, value) | Store a value for later in this same run |
ctx.get(key, default?) | Read it back; default if never set |
ctx.has(key) | true/false — was it set |
// Pre-request Script
ctx.set("startedAt", fn.timestamp());
// Validation / Rules, same run
res.setBody("elapsed", fn.timestamp() - ctx.get("startedAt", 0));Using Functions in Rules (Sandbox & Interceptor)
Functions behave identically in Studio templating and in the rule engine — only the call form and the object you write to change.
| Context | Prefix | Write-back object |
|---|---|---|
| Studio request body | {{$fn()}} | — (resolves in place) |
| Studio Pre-request Script | fn. | req (request) |
| Sandbox (Host) rule | fn. | res (response), req (incoming request) |
| Interceptor request rule | fn. | ireq |
| Interceptor response rule | fn. | ires |
emv and ctx (sections 13–14) are bound wherever fn is. JWE and MAC (section 12) aren't separate bindings at all — they're methods on whichever message object (req/res/ireq/ires) is in scope.
req, res, pv, fn, emv and ctx bound too, so all of the above run there. In practice you'll mostly use print() for logging and fn.* verification functions (compare, match, startsWith, isPastDate, typeOf) for assertions — generator functions (generateCard(), fn.guid(), etc.) work too, but writes don't feed back into the request/response being tested.Sandbox host response rule:
res.setBody("txnId", fn.guid());
res.setBody("cardNumber", fn.generateCard("16"));
res.setBody("amount", fn.generateAmount("4","2"));
res.setBody("pinBlock", "" + fn.generatePinBlock("1234", req.getBody("cardNumber"), "0", "API Keys"));Interceptor response rule (ires):
ires.setBody("traceId", fn.guid());
ires.setBody("stan", fn.generateRandomNumber("6"));ISO 8583 rules write to numbered fields, not JSON keys:
res.setBody("2", "" + fn.generateCard("16")); // PAN
res.setBody("4", "" + fn.generateRandomNumber("12")); // amount
res.setBody("11", "" + fn.generateRandomNumber("6")); // STAN
res.setBody("52", "" + fn.generatePinBlock("1234", req.getBody("2"), "0", "API Keys")); // PIN block, format 0