Programmable payments
For architects and developers automating payment logic. How PayScript scripts, automations and triggers fit together, and what each lifecycle allows.
When the bank wants payment logic to run
PayScript lets your bank define reusable payment logic and attach it to an automation. A supported trigger determines when the automation runs, for example a schedule, an available-balance crossing or a direct request. Importing a script alone does not start payments.
The business owner defines the intended rule and exceptions. Engineers prepare the approved script, and authorised administrators manage its version and automation settings. Instructions still follow the platform's configured policy, signing and settlement path.
Before relying on a workflow, confirm its supported actions with the service owner and agree how its results will be verified. The current customer API cannot read an automation run's final outcome and sends no run-outcome notification. An active automation or an accepted run is therefore insufficient evidence that a payment succeeded. The configuration and lifecycle details follow below.
From payment logic to an automation
A published script supplies the logic. An active automation selects that version, adds its settings and makes a supported trigger eligible to start work. Keep setup and execution evidence separate.
%%{init: {"theme": "neutral"}}%%
flowchart TB
Logic["Review the supported payment logic"] --> Publish["Import and publish a script version"]
Publish --> Bind["Bind the version to an automation"]
Bind --> Trigger["A supported trigger starts a run"]
Trigger --> Evidence["Obtain operator evidence of its result"]
Confirm the supported actions and trigger behaviour in your environment. The current customer API cannot read a run's final outcome, and no automation-run notification is sent. Publishing a script or activating an automation does not establish that a payment settled.
View in API Reference
The model
PayScript is Quant Network's language for programmable money, built on Groovy. Banks use it to define payment rules, conditions and automated workflows. Automations can mint, transfer and burn tokens under the conditions a script sets.
| Concept | What it is |
|---|---|
| Script | A YAML document declaring a trigger type, a trigger block, parameters and a code body. Scripts are versioned. |
| Automation | Binds one published script version to a trigger, with values for the script's parameters. An automation is what runs. |
| Trigger | Sets when an automation runs. |
| Run | One execution of an automation. |
Importing a script does not run it. A script runs only once it is published and an automation binds it to a trigger.
All scripts and automations are scoped to your organisation, taken from the access token.
How PayScript fits into a bank integration
Use PayScript when the platform should decide when to request work: at a scheduled time, after an available-balance threshold is crossed, or after an explicit call from your backend. Keep instructions in your bank adapter when the bank needs to control each submission directly.
The script describes reusable logic. The automation selects a published version of that logic and supplies its settings. For example, two scheduled workflows can use the same approved script with different account parameters. Publishing the script makes it available for binding; creating an active automation makes its trigger eligible to fire. Neither action proves that a payment has settled.
PayScript is designed to orchestrate Treasury operations through the platform's existing settlement path. It does not give scripts direct access to signing keys or raw blockchain transactions. The configured policy checks and custody controls still matter for the instructions it produces. Read Operations and their lifecycle and Policy, approvals and audit alongside this guide.
Separate three facts in your application: the script version is published, the automation is active, and a particular run was accepted. A fourth fact, successful execution, needs execution evidence that the public API currently cannot return. Do not display an active automation as proof that all its runs succeeded.
Scripts
A script document has four parts.
| Part | Required | Content |
|---|---|---|
triggerType | Yes | TIME, BALANCE, TRANSACTION or ON_DEMAND. |
trigger | Per trigger type | The trigger's values. ON_DEMAND takes no trigger block. |
params | No | The settings the code may refer to, each with a key, a type, a label and whether it is required. |
code | Yes | The code body, in Groovy. |
The document is uploaded as a file of up to 50 KB. When it is saved, the structured fields are validated and the code is compiled under a restricted allow-list. The code may use only built-in actions and the parameters the document declares. Any other name is rejected when the script is saved.
The script sandbox
Script code runs in a restricted sandbox. It cannot declare packages, define closures or define new methods, and it can call only an explicit allow-list of methods. A script therefore cannot reach platform or language functions outside that list.
- Use only actions supported by the imported script and the deployed execution engine. The public API does not publish a complete callable-action catalogue; obtain the approved action names, arguments and effects before writing new script code.
- Confirm the execution identity and policy path for script-submitted instructions in your environment. A script compiling successfully does not prove it has settlement authority or passes the intended approval gates.
Parameter types are BOOL, INT, DECIMAL, STRING, the _ARRAY form of each, ACCOUNTINFO and BALANCE.
Script lifecycle
| Status | Meaning |
|---|---|
UNPUBLISHED | Imported, not yet usable by automations. Its document can be replaced in place while no automation is linked to it. |
PUBLISHED | Automations can bind to it. Publishing a script also publishes every script it depends on. |
OUTDATED | Superseded by a newer version. Automations already bound to it keep running against it. |
DEPRECATED | Superseded. Automations report it through scriptStatus. |
DELETED | Soft-deleted. Reads return 404. Linked automations are disabled. |
Replacing the code of a PUBLISHED script creates the next version, UNPUBLISHED, and marks the edited version OUTDATED. Every version shares a rootScriptId, so you can find all automations still running on any version of a script with one call.
Triggers
| Trigger | Fires | Trigger values |
|---|---|---|
ON_DEMAND | When you call POST /api/automations/{automationId}/executions. | None |
TIME | At each occurrence of its schedule. | occurrence and occurrenceDetails, for example daily at 09:00 UTC |
BALANCE | When a confirmed Treasury transaction takes an account's available balance across its limit. | account, balance (for example < 500), currency |
TRANSACTION | Accepted by the script schema. | payer and/or payee, optional amount with currency, optional reference |
Account fields in a trigger take the keywords OWNER, any, anyExcept(a, b), or a concrete account identifier.
- Validate each trigger you use in the assigned environment. Schema acceptance of
TRANSACTIONdoes not by itself establish that the trigger is executed. - Test the documented available-balance crossing after a confirmed operation; a pending instruction or the account remaining below the threshold does not establish a new crossing.
Understand a balance crossing
The PayScript integration guide specifies available balance, evaluated when a confirmed Treasury transaction takes the watched account across its configured limit. It is event-driven, rather than a promise to poll the account continuously.
For a condition below 500.00 GBP, a confirmed payment that changes available balance from 600.00 to 450.00 crosses the limit. The account simply remaining at 450.00 is not another crossing. A pending payment does not establish the confirmed balance change. Test the crossing in your assigned environment with an approved script and obtain execution evidence before relying on the automation.
For scheduled runs, configure the required timeZone as well as the occurrence details. Keep the schedule's time zone separate from response timestamps, which are UTC. For direct runs, use an ON_DEMAND script and the execution endpoint.
Automations
An automation binds a PUBLISHED script to a trigger. Its triggerType must match the one the script declares, and its parameter values must fit the script's declared parameters. It is created ACTIVE and owned by the user who created it.
| Status | Meaning | Allowed transitions |
|---|---|---|
ACTIVE | Can fire. | to INACTIVE |
INACTIVE | Paused. | to ACTIVE, or to DISABLED |
DISABLED | Permanently stopped. Terminal. | none |
DELETED | Soft-deleted through DELETE. Still listed, keeps its history, cannot run. | none |
Every creation and status change is recorded in the automation's history, with who made it and when.
An ON_DEMAND automation can be run by anyone in the organisation. A run can override the automation's parameter values for that run only. Overrides are never written back.
Runs
Requesting a run returns 202 with an executionId. The acknowledgement is not a run record.
The API does not expose run records or run outcomes. There is no endpoint to read whether a run succeeded, what it did, or why a trigger did or did not fire. No webhook event is sent for automation runs. Keep your own execution-request record and obtain operator evidence when a run outcome is needed. A 202 is acceptance and cannot be reported to users as successful execution.
Correlate observed transactions with your own business instruction and operator-supplied execution evidence. The public API does not promise a run-to-transaction correlation field.
The executionId is derived from the Idempotency-Key and the automation id. Retrying with the same key replays the first 202 with Idempotency-Replayed: true and does not start a second run.
Change a payment workflow without losing version history
Before replacing a published script, list its versions using any version's script ID, and list its automations using the lineage's rootScriptId filter. A new script version does not migrate existing automations: they retain the version they were bound to, even when it is OUTDATED.
Publish the replacement script and prepare its reviewed parameters. Plan the handover so both versions do not issue the same business instruction: creating an automation makes it ACTIVE immediately, so pause the old automation before creating the replacement. This handover can introduce a gap; account for scheduled occurrences and any already accepted runs with the operator. After verifying the handover, permanently disable the old automation if it is no longer needed. Retain the script version, automation ID and execution request in your evidence records.
Deprecation applies to an OUTDATED script version. It is refused while automations on that version remain ACTIVE; remaining automations are disabled when deprecation succeeds. It is terminal. Use Write and run an automation for the actual requests and script recipes for download, clone and version-history examples.
Worked example
Run an ON_DEMAND automation, overriding one parameter for this run.
POST /api/automations/c33d1f7a-9e21-4b8c-a6d2-0f3b7c9e5a44/executions HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer <access token>
API-Version: 1.0.0
Content-Type: application/json
Idempotency-Key: 2b6d9f14-7c3e-4a58-b1d0-9e5f3a7c2d86
{
"parameterOverrides": [
{ "key": "savingsAccount", "value": "acc_777", "type": "STRING" }
]
}HTTP/1.1 202 Accepted
Content-Type: application/json
{
"executionId": "5f2c8a1e-3b4d-5e6f-9a0b-1c2d3e4f5061",
"automationId": "c33d1f7a-9e21-4b8c-a6d2-0f3b7c9e5a44",
"createdAt": "2026-08-18T11:26:46.312Z",
"parameters": [
{ "key": "savingsAccount", "value": "acc_777", "type": "STRING" }
]
}PayScript timestamps are ISO 8601 UTC instants with fixed millisecond precision, for example 2026-08-18T11:26:46.312Z.
A script document looks like this (from the API Reference):
triggerType: BALANCE
trigger:
account: OWNER
balance: < 500
currency: GBP
params:
- key: topUpTo
type: DECIMAL
required: true
label: Top up to
code: |
logMessage("Balance fell below the limit; topping up to " + topUpTo.toString());The source example uses OWNER; treat it as an example to validate against the deployed engine rather than a substitute for checking the imported script's trigger rules.
View in API Reference
- Run an on demand automation ·
POST
Errors and edge cases
| Situation | Response |
|---|---|
| Script fails validation or compilation, or its name is already used | 400, naming the field or compilation error |
Creating an automation from a script that is not PUBLISHED | 409 |
Running an automation that is not ACTIVE or not ON_DEMAND | 409 |
A run override with an unknown key, or a value that does not parse as its type | 422 |
Missing Idempotency-Key on a run request | 400 |
An earlier request with the same Idempotency-Key still in progress | 409 |
| A disallowed automation status transition, including to its current status | 400 |
Deleting a PUBLISHED script, or one with ACTIVE automations or dependants | 409 |
API Reference
Open an endpoint for request fields, response examples and the interactive API console.
| Operation | Method |
|---|---|
| Import a script | POST |
| Get a script | GET |
| Update a script | PATCH |
| Create an automation | POST |
| List automations | GET |
| Update an automation's status | PATCH |
| Get an automation's status change history | GET |
| Run an on demand automation | POST |
Related pages
Implementation resources
Use Implement a backend client for request handling, durable idempotency and outcome tracking. The developer integration coverage map links every public operation to its API Reference and contract-derived code recipe. Replace example identifiers with values from your assigned environment.
Updated 2 days ago

