Learn how to use TxScript to create formula fields for document extraction
Formula Fields use the tx capability object to validate, transform, and enrich field values during document extraction. Formula fields run server-side in the context of a single document.
Formula fields are perfect for:

You can add or edit formula fields in the Apps → Document Types → Header Fields or Line Item Fields section.
Setting the Hidden flag will hide the field from the UI
Formula fields provide a powerful way to integrate with external systems such as your ERP, CRM, accounting software, or any database. This enables real-time data synchronization and validation during document extraction.
You can interact with external systems using HTTP requests through the tx.http.request() method. This allows you to:
All HTTP requests go through the tx.http.request() method, which provides:
Here's a simple example of fetching data from an external API:
// Fetch product information from ERP system
const sku = tx.getCurrentLineItem()?.sku;
if (sku) {
const response = await tx.http.request({
url: "https://your-erp-system.com/api/products",
method: "GET",
headers: {
"Authorization": "Bearer YOUR_API_TOKEN"
},
body: { sku: sku }
});
if (response.ok && response.body) {
tx.setCurrentLineField("description", response.body.name);
tx.setCurrentLineField("price", response.body.price);
}
}
See the HTTP Requests section below for detailed API documentation.
Formula fields receive a tx capability object as their only parameter. The code runs in the context of either a header field or a line item field:
// Example: Lookup product description from SKU
const lineItem = tx.getCurrentLineItem();
const sku = lineItem?.sku;
if (!tx.utils.isNonEmptyString(sku)) {
tx.addMessage("SKU is required", { level: "error", field: "sku" });
return;
}
// Lookup in dataset
const product = tx.dataset.lookup("sku2en", "SKU", sku);
if (!product) {
tx.addMessage(`SKU "${sku}" not found in catalog`, {
level: "warning",
field: "sku"
});
return;
}
// Set description from dataset
tx.setCurrentLineField("description", product["English Item Name"]);
// Set the result
tx.setResult(product["English Item Name"]);
// Get a single header field
const vendorName = tx.getField("vendorName");
// Get multiple header fields at once
const { date, currency, totalAmount } = tx.getFields(["date", "currency", "totalAmount"]);
// Get the current line item (when running in a line-item context)
const currentItem = tx.getCurrentLineItem();
const sku = currentItem?.sku;
// Get a specific line item
const item = tx.getLineItem("items", 0);
// Get all line items from a collection
const allItems = tx.getLineItems("items");
// Get current collection context
const collectionKey = tx.getCurrentCollection(); // e.g., "items"
const index = tx.getCurrentIndex(); // e.g., 0
// Get the complete document context
const context = tx.getContext();
// Returns: { header: {...}, lineItems: {...}, file: {...} }
// Set the computed result for a formula field
tx.setResult(computedValue);
// Set a single header field
tx.setField("vendorName", "Acme Corp");
// Set multiple header fields
tx.setFields({
vendorName: "Acme Corp",
date: "2025-01-15",
currency: "USD"
});
// Set a field on a specific line item
tx.setLineField("items", 0, "description", "Product Name");
// Set a field on the current line item (when in line-item context)
tx.setCurrentLineField("description", "Product Name");
Datasets are pre-loaded lookup tables that you can query:
// Get all rows from a dataset
const allRows = tx.dataset.getAll("sku2en");
// Find first matching row
const match = tx.dataset.find("sku2en", (row) => row.SKU === sku);
// Find all matching rows
const matches = tx.dataset.filter("sku2en", (row) => row.Category === "Electronics");
// Lookup by field value (case-insensitive field names)
const product = tx.dataset.lookup("sku2en", "SKU", sku);
Make HTTP requests to external APIs (customer-owned endpoints):
// Simple GET request
const response = await tx.http.request({
url: "https://api.example.com/products",
method: "GET"
});
// POST request with body
const response = await tx.http.request({
url: "https://api.example.com/validate",
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: { sku: "12345" },
timeoutMs: 10000 // Optional timeout override
});
// Response structure
if (response.ok) {
const data = response.body; // Parsed JSON if applicable
const text = response.bodyText; // Raw text
const status = response.status; // HTTP status code
}
Add user-facing notifications:
// Info message
tx.addMessage("Processing completed successfully", { level: "info" });
// Warning message
tx.addMessage("SKU not found in catalog", {
level: "warning",
field: "sku" // Optional: field name for line-item context
});
// Error message
tx.addMessage("Failed to validate product", { level: "error" });
// Check if value is a non-empty string
if (tx.utils.isNonEmptyString(value)) {
// value is guaranteed to be a string
}
// Parse number from string or number
const num = tx.utils.parseNumber("123.45"); // Returns 123.45 or null
// Check if value is nullish
if (tx.utils.isNullish(value)) {
// value is null or undefined
}
// Format currency
const formatted = tx.utils.formatCurrency(1234.56, "USD"); // "$1,234.56"
Log messages for debugging:
tx.log("debug", "Processing SKU", { sku: "12345" });
tx.log("info", "Validation complete");
tx.log("warn", "Rate limit approaching");
tx.log("error", "API request failed", { status: 500 });
// Get current line item
const lineItem = tx.getCurrentLineItem();
const sku = lineItem?.sku;
if (!tx.utils.isNonEmptyString(sku)) {
tx.addMessage("SKU is required", { level: "error", field: "sku" });
return;
}
// Lookup in dataset
const product = tx.dataset.lookup("sku2en", "SKU", sku);
if (!product) {
tx.addMessage(`SKU "${sku}" not found in catalog`, {
level: "warning",
field: "sku"
});
return;
}
// Set description from dataset
tx.setCurrentLineField("description", product["English Item Name"]);
// Set the result
tx.setResult(product["English Item Name"]);
// Get current line item
const lineItem = tx.getCurrentLineItem();
const sku = lineItem?.sku;
if (!tx.utils.isNonEmptyString(sku)) {
return;
}
// Validate via external API
try {
const response = await tx.http.request({
url: "https://api.example.com/validate",
method: "POST",
body: { sku: sku }
});
if (response.ok && response.body.valid) {
tx.setCurrentLineField("validated", true);
tx.setCurrentLineField("validationDate", new Date().toISOString().split('T')[0]);
} else {
tx.addMessage("Product validation failed", {
level: "warning",
field: "sku"
});
}
} catch (error) {
tx.log("warn", "Validation API unavailable", { error: error.message });
tx.addMessage("Could not validate product", {
level: "info",
field: "sku"
});
}
tx.setResult(lineItem.description || sku);
// Get header fields
const subtotal = tx.getField("subtotal");
const taxRate = tx.getField("taxRate");
// Parse numbers
const subtotalNum = tx.utils.parseNumber(subtotal) || 0;
const taxRateNum = tx.utils.parseNumber(taxRate) || 0;
// Calculate total
const taxAmount = subtotalNum * (taxRateNum / 100);
const total = subtotalNum + taxAmount;
// Set calculated fields
tx.setField("taxAmount", taxAmount);
tx.setField("total", total);
// Set result
tx.setResult(total);
// Get header fields
const vendorName = tx.getField("vendorName");
const invoiceNumber = tx.getField("invoiceNumber");
const date = tx.getField("date");
// Validate required fields
const errors = [];
if (!tx.utils.isNonEmptyString(vendorName)) {
errors.push("Vendor name is required");
}
if (!tx.utils.isNonEmptyString(invoiceNumber)) {
errors.push("Invoice number is required");
}
if (!tx.utils.isNonEmptyString(date)) {
errors.push("Date is required");
}
// Validate date format (YYYY-MM-DD)
if (tx.utils.isNonEmptyString(date)) {
const dateRegex = /^\d{4}-\d{2}-\d{2}$/;
if (!dateRegex.test(date)) {
errors.push("Date must be in YYYY-MM-DD format");
}
}
// Add error messages
if (errors.length > 0) {
errors.forEach(error => {
tx.addMessage(error, { level: "error" });
});
return;
}
// All validations passed
tx.setResult("Valid");
Formula fields run in one of two contexts:
tx.getField()tx.setField()tx.getCurrentLineItem()tx.getLineItem() or tx.getLineItems()tx.setCurrentLineField()tx.getField()tx.setResult() with the computed valueFormula fields run during document extraction. They have access to the document's header and line items, but cannot access organization-wide data like mini-apps and tasks can.
On This Page
OverviewExternal System IntegrationHow It WorksExample Use CasesMaking HTTP RequestsQuick StartCore APIReading DataHeader FieldsLine ItemsFull ContextWriting DataSetting ResultsSetting Header FieldsSetting Line Item FieldsDataset AccessNOTE - Datasets are currently deprecated - the code still exist but not in use in any real pathHTTP RequestsNotifications and MessagesUtilitiesLoggingComplete ExamplesExample 1: SKU to Description LookupExample 2: External API ValidationExample 3: Calculate Total with TaxExample 4: Multi-Field ValidationExecution ContextHeader Field ContextLine Item Field ContextSecurity & LimitsBest Practices