Custom Scripts & Flows

Two ways to automate work beyond what a form and an approval chain can do on their own.

ℹ️ Who is this for? Building and running Custom Scripts and Flows is limited to the platform's systemadmin account, which the Persiv team operates. A user with the System Admin role can't open either one. To have something automated, contact the Persiv team. Users can still see a flow's run status on their entries, and approve a flow step that is waiting on them.

Custom Scripts

A Custom Script is a small piece of Python code, stored in the platform and run automatically at a specific point in a smarttable's lifecycle — no separate deployment, no server access needed. Use it when a form field, a formula, or an approval step isn't enough: sending a message to an external system, running a calculation too complex for the Formula Engine, or generating data from another smarttable on the fly.

When a script runs (hook points)

HookRuns
Before SaveJust before an entry's data is written — can modify or reject the save
After SaveRight after an entry is saved
Before SubmitJust before an entry is submitted
After SubmitRight after an entry is submitted
Before DisplayJust before an entry's Display/Print/PDF view is rendered — can inject computed values
After Get EntriesRight after the entries table is fetched — can post-process the list
Notification ActionWhen a user takes action (approve/reject) on a notification
Scheduled / CronOn a recurring schedule, independent of any entry being saved — for periodic sync/cleanup jobs

What a script can do

Scripts run against a controlled API, not raw database access:

  • Read/write smarttable data — query and update entries in this or other smarttables
  • Send notifications — trigger the same in-app/push notification system described on the Notifications page
  • Call external services — make HTTP requests out to another system
⚠️ Scripts run with real access A script can read and write real data and call out to external systems. Only the systemadmin account can create, edit or run scripts. Every create, edit, run, rollback and delete is recorded in the audit log. Treat script authorship the same as any other trusted-code change — review it before it goes live.

Where to manage scripts

Scripts are written and tested in a dedicated in-app code editor (a full syntax-highlighted Python editor, not a plain textarea). Its toolbar has:

ButtonWhat it does
Save (⌘/Ctrl+S)Saves the script. If the code changed, you're asked for an optional change note and a new version is recorded.
Test Run (⌘/Ctrl+Enter)Runs the script once with the parameters set under Edit Test Params (a JSON object), and shows the output below the editor
Run NowRuns the script once for real, outside its hook or schedule
Version HistoryLists every saved version of the code (see below)
Execution LogsLists the script's recent runs (see below)

A scheduled script also has two settings that hook scripts don't: Failure emails (addresses emailed when a scheduled run fails) and a timeout. A hook script's failure shows up on the save or submit that triggered it.

Version history and rollback

Each save that changes the code adds a numbered version (v1, v2, …), recording the code, the change note, who saved it and when. Saving without changing the code (for example, only renaming the script) doesn't add a version.

To go back to an earlier version, open Version History and click its rollback button. That version's code becomes the live code, and the rollback is recorded as a new version noted Rollback to vN. Nothing is deleted, so a rollback can itself be undone by rolling back again.

Execution logs

Execution Logs shows the script's 50 most recent runs, newest first. Each run shows:

  • Result: success or failed
  • Duration in milliseconds
  • How it was triggered: hook, schedule, manual (Run Now) or test (Test Run)
  • Who triggered it (System when no user started it, such as a scheduled run) and when
  • Output, expandable: anything the script printed, any error, and its return value

The scripts dashboard also lists the 10 most recent failed runs across all scripts.

Flows

Flows are a no-code, drag-and-drop way to automate a sequence of steps — build it visually as a flowchart instead of writing code. Use a Flow when you need "when X happens, do Y, then Z" without wanting to write a Custom Script for it.

How a Flow works

  1. Pick a trigger — what starts the flow. Supported today: a record being created or updated on a chosen smarttable, a manual run, or an API call from another system (see below).
  2. Add nodes on the visual canvas — each node is one step (e.g. send a notification, update a field, branch on a condition).
  3. Connect the nodes in the order they should run, including branches for different conditions.
  4. Publish the flow to make it live. A published flow can be paused and resumed at any time without losing its configuration.

Reviewing runs

Every time a flow runs, it's logged as a Run with a full step-by-step record of what each node did — useful for confirming a flow behaved as expected, or diagnosing why it didn't. Runs that include an approval-style step pause and wait for a person to act, the same way a notification-driven approval does elsewhere in the platform.

Starting a Flow from Another System

A flow whose trigger is set to API call can be started by another system, such as PersivX, with an HTTP request. There's no smarttable involved: the JSON the caller sends becomes the run's data, and the flow's steps refer to its keys (for example {{customer_email}}).

API keys

Calls are authenticated with an API key. Keys are managed in the flow builder: select an API-call trigger and use the API keys (org-wide) box under its Trigger URL.

  • Create: enter a name (e.g. PersivX integration) and click +. The full key, starting pfk_, is shown once. Copy it then: only a hash is stored, so it can't be shown again.
  • Scope: a key belongs to the organization, not to one flow or one person. It can start any published API-call flow in that organization, and doesn't expire.
  • Revoke: click the bin icon next to the key. Any system still using it is refused from the next call. Keys are listed by name and their first few characters only.

Creating and revoking keys is limited to the systemadmin account, and both are recorded in the audit log.

Making the call

The flow's Trigger URL (with a copy button) is shown in the same trigger panel. The calling system sends:

Request
POST <Trigger URL>
Authorization: Bearer pfk_…
Content-Type: application/json

{"customer_email": "a@example.com", "order_no": "SO-1042"}
  • The body can be a single JSON object (one record), or {"rows": [ {...}, {...} ]} to run the flow over several records at once.
  • To make retries safe, send an Idempotency-Key header. A second call with the same key returns the run that was already started instead of starting another.
  • A successful call returns 201 with the queued run. The run then appears under the flow's runs like any other.
ResponseMeaning
403Missing, wrong or revoked key
404No such flow in the key's organization
400The flow isn't published and active, or its trigger isn't set to API call, or the body is malformed
⚠️ Publish first Only a published, active flow can be started this way. A draft or paused flow refuses the call, even with a valid key.
💡 Custom Script vs. Flow — which one? Reach for a Flow first — it's visual, no code, and covers most "when this happens, do that" automation. Drop down to a Custom Script only when you need something a Flow's node types can't express, like a bespoke calculation or a call to an external API with custom logic.