About two minutes. To keep files on your machine, run the same operation locally.
1. Get an API key
Create an account or sign in. Open Setup → API keys in the console and choose Create API key. A new account gets a free trial of 100 successful output files for 30 days, with no card. A run that returns several files counts once per file. Then Platform or Enterprise continues. Keep the key in an environment variable:
export RUNSTAMP_API_KEY=pj_live_YOUR_KEY2. Send a sample document
Download the sample workbook. Ask Runstamp to write "Ready for review" into cell E2 of its Remediation sheet.
SAMPLES=https://runstamp.com/demo-evidence/operation-evidence
curl -fsSL -o sample.xlsx \
"$SAMPLES/xlsx/xlsx.transform/input-01-workbookBase64.xlsx"
RUNSTAMP=https://runstamp.com/api/v2
curl "$RUNSTAMP/operations/xlsx/transform" \
-H "Authorization: Bearer $RUNSTAMP_API_KEY" \
-H "Idempotency-Key: quick-start-$(date +%s)" \
-H "Runstamp-Document-Name: sample.xlsx" \
-H "Content-Type: application/json" \
-d @- <<JSON
{
"input": {
"workbookBase64": "$(base64 < sample.xlsx | tr -d '\n')",
"artifactId": "quick-start-workbook",
"writes": [{
"locator": {
"artifactId": "quick-start-workbook",
"scheme": "xlsx.a1",
"value": ["Remediation", "E2"]
},
"value": "Ready for review"
}]
}
}
JSONimport { readFile } from "node:fs/promises";
const RUNSTAMP = "https://runstamp.com/api/v2";
const workbook = await readFile("sample.xlsx");
const response = await fetch(`${RUNSTAMP}/operations/xlsx/transform`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RUNSTAMP_API_KEY}`,
"Idempotency-Key": crypto.randomUUID(),
"Runstamp-Document-Name": "sample.xlsx",
"Content-Type": "application/json",
},
body: JSON.stringify({
input: {
workbookBase64: workbook.toString("base64"),
artifactId: "quick-start-workbook",
writes: [{
locator: {
artifactId: "quick-start-workbook",
scheme: "xlsx.a1",
value: ["Remediation", "E2"],
},
value: "Ready for review",
}],
},
}),
});
const run = await response.json();
console.log(run.id, run.status_url);Runstamp returns 202 Accepted and the run ID:
{
"id": "4f6c2a8e-9b1d-4c3e-8a57-2d0f1e6b9c41",
"status": "queued",
"status_url": "/api/v2/executions/4f6c2a8e-9b1d-4c3e-8a57-2d0f1e6b9c41",
"result_url": "/api/v2/executions/4f6c2a8e-9b1d-4c3e-8a57-2d0f1e6b9c41/result",
"reused": false
}3. See the run
Open https://runstamp.com/dashboard/runs/RUN_ID to see the changed cell, the checks run and the file. From code, poll the status URL, then download the result:
RUNSTAMP=https://runstamp.com/api/v2
curl "$RUNSTAMP/executions/RUN_ID" \
-H "Authorization: Bearer $RUNSTAMP_API_KEY"
curl -L "$RUNSTAMP/executions/RUN_ID/result" \
-H "Authorization: Bearer $RUNSTAMP_API_KEY" \
-o result.jsonA large result returns a 307 redirect, so keep -L. For files over 4 MiB, see Large inputs and results.
The result is JSON. The changed workbook is inside it as base64 at value.output.bytes.data, beside the receipt and the list of changes. Once the status is succeeded and the result has "ok": true, save the file with jq:
jq -r '.value.output.bytes.data' result.json | base64 --decode > output.xlsxUse the Runstamp Managed API to set cell E2 on the "Remediation" sheet of the sample workbook below to "Ready for review", wait for the run to finish, and print the run ID.
Sample workbook: https://runstamp.com/demo-evidence/operation-evidence/xlsx/xlsx.transform/input-01-workbookBase64.xlsx
POST the base64 workbook to https://runstamp.com/api/v2/operations/xlsx/transform with Authorization: Bearer $RUNSTAMP_API_KEY and an Idempotency-Key header, then poll the returned status_url until the run finishes. Docs for agents: https://runstamp.com/llms.txt
Run it locally with the SDK
The same operation runs in your process with the SDK. No account or API key is needed, and the workbook stays on your machine.
1. Install and initialize
npm install @runstamp/sdkimport { writeFile } from "node:fs/promises";
import { runstamp } from "@runstamp/sdk";
const SAMPLES = "https://runstamp.com/demo-evidence/operation-evidence";
const source = Buffer.from(await fetch(
`${SAMPLES}/xlsx/xlsx.transform/input-01-workbookBase64.xlsx`,
).then((response) => response.arrayBuffer()));
const artifactId = "security-remediation-workbook";The local transport runs the stable catalog in your process. The workbook is not sent to hosted execution.
2. Find the cell to change
Map the cell your app will change. In production, use a defined name or native table if the customer template has one. This sample uses a known A1 cell.
const mapped = await runstamp.operations.run("xlsx.transform", {
workbookBase64: source.toString("base64"),
artifactId,
targets: [{
id: "remediation-status",
kind: "a1",
sheet: "Remediation",
ref: "E2",
}],
});
if (!mapped.ok) throw new Error(`${mapped.error.code}: ${mapped.error.remediation}`);
const target = mapped.value.output.mappings[0]?.locator;
if (!target) throw new Error("The requested target was not resolved.");
const before = await runstamp.operations.run("xlsx.parse", {
workbookBase64: source.toString("base64"),
artifactId,
locators: [target],
});
if (!before.ok) throw new Error(`${before.error.code}: ${before.error.remediation}`);
console.log("Current value:", before.value.output.cells[0]?.value);Before writing, show the resolved target and current value to the owner of the change.
3. Change and verify the existing file
const changed = await runstamp.operations.run("xlsx.transform", {
workbookBase64: source.toString("base64"),
artifactId,
writes: [{
locator: target,
value: "Ready for review",
}],
});
if (!changed.ok) {
throw new Error(`${changed.error.code}: ${changed.error.remediation}`);
}
const ladder = changed.verification?.ladder;
if (ladder?.valid.state !== "pass"
|| ladder.preserved.state !== "pass"
|| ladder.intendedChangeVerified.state !== "pass") {
throw new Error("The changed workbook did not pass the required mutation checks.");
}
await writeFile("remediation-reviewed.xlsx", changed.value.output.bytes);The operation reopens the output, checks its package structure, confirms the declared value exists, and checks that content outside the target did not change. A no-op or unobserved change returns a typed failure.
4. Know what was not checked
console.log(changed.verification);
// valid: pass
// preserved: pass
// intendedChangeVerified: pass
// deliveryReady: not_checked
// businessCorrectness: not_verifiableThis check does not show that Excel renders the workbook correctly in your recipient's apps and versions. It does not prove the status fits the business. Run those checks before delivery or require them in a managed acceptance profile.
Use the same operation elsewhere
The operation name, schemas, result envelope, errors, losses, receipt and verification evidence keep the same shape across the local SDK, CLI, MCP and Managed API.