Cron Standing Orders

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"
}
FieldMeaning
accountIdThe user's account to debit.
destinationAccountIdThe corporate wallet account in the same currency (64013 otherwise).
amountInteger in the smallest unit of the currency: cents, satoshis, wei (64014 otherwise). This amount is transferred on every run.
frequencyDAILY, WEEKLY or MONTHLY.
startDateFirst 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).
endDateOptional last date on which a run may happen, not before startDate (64015 otherwise). The order completes after the last run.
memoOptional, up to 100 characters, attached to every transfer.
verificationMethodSCA-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:

ResultOrderWebhook
Executedstays ACTIVE; runCount, lastRunAt, lastRunOutcome and nextRunAt are updatedINTER_LEDGER_SEND only. CRON_STANDING_ORDER_COMPLETED as well when it was the last run before endDate.
Executed, but held for compliance reviewstays ACTIVECRON_STANDING_ORDER_HELD, then the usual Transaction Under Review webhook
Balance below amountPAUSED, pauseReason: INSUFFICIENT_BALANCECRON_STANDING_ORDER_PAUSED
User no longer KYC approved and activePAUSED, pauseReason: OWNER_NOT_ELIGIBLECRON_STANDING_ORDER_PAUSED
Source or destination account unavailable (not active, INTER permission or Payment Accounts consent missing)PAUSED, pauseReason: SOURCE_UNAVAILABLE or DESTINATION_UNAVAILABLECRON_STANDING_ORDER_PAUSED
Feature switched off for your applicationPAUSED, pauseReason: DISABLED_FOR_APPLICATIONCRON_STANDING_ORDER_PAUSED
User limit exceeded, or SCA lock activestays ACTIVE; the run is skipped (skipCount +1) and the next one scheduledCRON_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-all with type: "CRON" lists the user's cron orders; status filters on ACTIVE, PAUSED, CANCELLED or COMPLETED. Without type the endpoint keeps listing swap standing orders.
  • POST /standing-orders/get-by-id returns either kind; cron results carry type: "CRON".
  • POST /standing-orders/cancel followed by /confirm cancels an ACTIVE or PAUSED order, as for swap standing orders. Cancelling a CANCELLED or COMPLETED order returns 64017.

The business standing-order endpoints do not support cron orders.

Errors

CodeMeaning
30077The destination is a corporate wallet not allowed for transfers from your users (see Prerequisites).
64012destinationAccountId is not an account of a corporate wallet your application allows for cron standing orders.
64013Source and destination currencies differ.
64014amount is not a positive integer in the smallest unit.
64015startDate is not strictly after today, or endDate is before startDate.
64016An ACTIVE or PAUSED cron order already exists for this source and destination.
64017The order is not in a state that allows the operation (resume, cancel).
64018verificationMethod is not permitted for this source (totp on EUR and USDC).
64019Cron 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.