Scheduled transfers of a fixed amount from a user's account to your corporate wallet
A cron standing order moves a fixed amount from one of your user's accounts to the same-currency account of a dedicated corporate wallet of your application on a schedule: daily, weekly or monthly, at 00:00 UTC. Unlike a swap standing order it does not react to deposits and never converts currency: it is a scheduled inter-ledger transfer that the user authorises once, at setup.
Cron standing orders reuse the standing-order endpoints. A create request with type: CRON makes one; every other request keeps creating swap standing orders exactly as before, and swap responses are unchanged (they carry no type field).
Prerequisites
To enable the feature, contact your sales manager at Striga. Striga sets up a dedicated corporate wallet for your application, with one account per enabled currency, and switches cron standing orders on. Both are per application and per environment, so the sandbox and production are enabled separately.
Your sales manager gives you the id of that wallet; it is also listed by Get All Corporate Accounts. The accountId of its account in the user's currency is the destinationAccountId of the order.
Once the feature is enabled, inter-ledger transfers from your users towards your corporate wallets are accepted only towards the wallets Striga has allowed for consumer transfers, which is normally the dedicated wallet alone. A transfer towards another corporate wallet, ad hoc or through a cron standing order, fails with 30077. Tell your sales manager if your users should keep sending to your default corporate wallet as well.
The user needs an enriched account in the order's currency with the INTER transfer permission, an approved KYC and, on SCA-enabled applications, an enrolled factor to confirm the setup with.
Creating an order
Call POST /standing-orders/create with type: CRON:
{
"userId": "4d9a0d3e-7a35-4f4c-a8ba-3a2b1a2e44f1",
"accountId": "e2a1d2d7f8c04b5db2e1b7f4d0d3b1b4",
"type": "CRON",
"destinationAccountId": "5d3b5e3d2a7a4f1d9f4cbe6c1e1f2a3b",
"amount": "2500",
"frequency": "MONTHLY",
"startDate": "2026-12-01",
"endDate": "2027-11-30",
"memo": "Monthly savings plan",
"verificationMethod": "sms",
"ip": "203.0.113.10"
}| Field | Meaning |
|---|---|
accountId | The user's account to debit. |
destinationAccountId | The corporate wallet account in the same currency (64013 otherwise). |
amount | Integer in the smallest unit of the currency: cents, satoshis, wei (64014 otherwise). This amount is transferred on every run. |
frequency | DAILY, WEEKLY or MONTHLY. |
startDate | First run, YYYY-MM-DD in UTC, strictly after today; defaults to tomorrow. A weekly order runs on that weekday, a monthly order on that day of the month (on the last day of shorter months). |
endDate | Optional last date on which a run may happen, not before startDate (64015 otherwise). The order completes after the last run. |
memo | Optional, up to 100 characters, attached to every transfer. |
verificationMethod | SCA-enabled applications: sms or passkey. totp is not accepted for EUR and USDC sources (64018). |
whitelistedAddressId, whitelistedIbanId, action, destinationCurrency, fixedFee and percentFeeBps are ignored for cron orders. The create call runs the same checks as an ad hoc inter-ledger transfer (INTER permission, Payment Accounts consent, SCA lock, the corporate wallet rule above) and refuses a second ACTIVE or PAUSED order for the same source and destination pair (64016).
The response is a challenge, confirmed like a swap standing order with POST /standing-orders/confirm. The confirmed order comes back with type: "CRON", status: "ACTIVE" and nextRunAt, its first run:
{
"id": "2328cacb-6b07-4a0e-9b0e-7c3c2f4f0a11",
"type": "CRON",
"userId": "4d9a0d3e-7a35-4f4c-a8ba-3a2b1a2e44f1",
"parentApplicationId": "9b1f3c62-1b1e-4d7e-8a0f-6a2c5f4e3d21",
"sourceAccountId": "e2a1d2d7f8c04b5db2e1b7f4d0d3b1b4",
"sourceWalletId": "0e7c1b2a-3d4e-4f50-9a6b-7c8d9e0f1a2b",
"destinationAccountId": "5d3b5e3d2a7a4f1d9f4cbe6c1e1f2a3b",
"destinationWalletId": "8c1d2e3f-4a5b-4c6d-9e7f-0a1b2c3d4e5f",
"currency": "EUR",
"amount": "2500",
"memo": "Monthly savings plan",
"frequency": "MONTHLY",
"anchorDate": "2026-12-01T00:00:00.000Z",
"endDate": "2027-11-30T00:00:00.000Z",
"nextRunAt": "2026-12-01T00:00:00.000Z",
"status": "ACTIVE",
"runCount": 0,
"skipCount": 0,
"createdAt": "2026-11-04T10:58:12.401Z",
"lastUpdatedAt": "2026-11-04T10:58:12.401Z"
}Runs
Every run is an inter-ledger transfer of amount from the user's account to the corporate wallet account, at 00:00 UTC on the scheduled day. It shows up like any other inter-ledger transfer: an INTER_LEDGER_SEND transaction webhook carrying the order's memo, and a line in both account statements. Before each run Striga re-checks the user (KYC approved and active, no SCA lock), both accounts, the user's limits, the balance and the feature setting. The result is one of:
| Result | Order | Webhook |
|---|---|---|
| Executed | stays ACTIVE; runCount, lastRunAt, lastRunOutcome and nextRunAt are updated | INTER_LEDGER_SEND only. CRON_STANDING_ORDER_COMPLETED as well when it was the last run before endDate. |
| Executed, but held for compliance review | stays ACTIVE | CRON_STANDING_ORDER_HELD, then the usual Transaction Under Review webhook |
Balance below amount | PAUSED, pauseReason: INSUFFICIENT_BALANCE | CRON_STANDING_ORDER_PAUSED |
| User no longer KYC approved and active | PAUSED, pauseReason: OWNER_NOT_ELIGIBLE | CRON_STANDING_ORDER_PAUSED |
| Source or destination account unavailable (not active, INTER permission or Payment Accounts consent missing) | PAUSED, pauseReason: SOURCE_UNAVAILABLE or DESTINATION_UNAVAILABLE | CRON_STANDING_ORDER_PAUSED |
| Feature switched off for your application | PAUSED, pauseReason: DISABLED_FOR_APPLICATION | CRON_STANDING_ORDER_PAUSED |
| User limit exceeded, or SCA lock active | stays ACTIVE; the run is skipped (skipCount +1) and the next one scheduled | CRON_STANDING_ORDER_SKIPPED |
A paused order does not retry by itself. Fix the cause (top up the account, complete the KYC, ...) and call POST /standing-orders/resume: the order returns to ACTIVE and runs at its next scheduled 00:00 UTC slot, not immediately. If endDate has passed by then, the resume completes the order instead. Resuming an order that is not PAUSED, or whose cause still applies, returns 64017.
A run that fails for a transient reason is retried on the same slot. A slot is never executed twice.
The payloads of the CRON_STANDING_ORDER_* events are documented under Cron Standing Order Webhooks.
Managing orders
POST /standing-orders/get-allwithtype: "CRON"lists the user's cron orders;statusfilters onACTIVE,PAUSED,CANCELLEDorCOMPLETED. Withouttypethe endpoint keeps listing swap standing orders.POST /standing-orders/get-by-idreturns either kind; cron results carrytype: "CRON".POST /standing-orders/cancelfollowed by/confirmcancels anACTIVEorPAUSEDorder, as for swap standing orders. Cancelling aCANCELLEDorCOMPLETEDorder returns64017.
The business standing-order endpoints do not support cron orders.
Errors
| Code | Meaning |
|---|---|
30077 | The destination is a corporate wallet not allowed for transfers from your users (see Prerequisites). |
64012 | destinationAccountId is not an account of a corporate wallet your application allows for cron standing orders. |
64013 | Source and destination currencies differ. |
64014 | amount is not a positive integer in the smallest unit. |
64015 | startDate is not strictly after today, or endDate is before startDate. |
64016 | An ACTIVE or PAUSED cron order already exists for this source and destination. |
64017 | The order is not in a state that allows the operation (resume, cancel). |
64018 | verificationMethod is not permitted for this source (totp on EUR and USDC). |
64019 | Cron standing orders are not enabled for your application. |
The other standing-order and inter-ledger errors (missing INTER permission, Payment Accounts consent, SCA lock, validation) apply unchanged.
Testing on the sandbox
Cron orders behave the same on the sandbox: runs happen at 00:00 UTC and there is no simulation endpoint. To see a run on the next day, create a DAILY order (the default startDate is tomorrow) and wait for midnight UTC. To see a pause and a resume, create an order whose amount exceeds the account balance, then top the account up with a simulated deposit and call /standing-orders/resume.

