Periodic Payments Sandbox

Test standing orders end-to-end against the open-finance-sandbox provider, using dedicated debtor accounts that resolve to each standing-order status defined by the spec.

A periodic payment (standing order) instructs the bank to repeat a payment on a schedule — for example, paying rent on the 1st of every month until an end date. Before going live against a real bank, you can validate your full integration against the open-finance-sandbox provider.

The sandbox is deterministic: the debtor account you pay from decides the standing order's outcome. Each sandbox debtor account is wired to a specific standing-order status, so you can reproduce every flow — an active standing order, a rejection, a cancellation, a pending state, or a multi-level-SCA partial — just by changing one field in your request. No real money moves and no real bank is contacted.

📘

Unlike single payments (which enter the sandbox as RCVD and are advanced later), a periodic payment adopts its final status immediately at creation. The status you get back from the create call is the standing-order status the chosen debtor account maps to.

How it works

  1. You create a periodic payment with providerId: "open-finance-sandbox" and includeFakeProviders: true.
  2. You set periodicPaymentInformation.debtorAccountNumber to one of the sandbox accounts in the status table below.
  3. On creation, the payment is saved with the status that account maps to, and a notification/webhook is fired.
  4. You read the status back with Get payment status, or override it for further testing with Update sandbox status.

Sandbox debtor accounts

Pick the debtor account that matches the outcome you want to test. The standing order is created directly in that status. These accounts are specific to periodic payments — using any other account returns 400 Debtor account is not a periodic-payment sandbox account.

Debtor account (debtorAccountNumber)StatusGroupMeaning
IL070311140000000435694ACTCActiveAccepted — technical validation passed. The standing order is active. This is the documented end status for periodic payments.
IL630310640000000406821ACWCActiveAccepted with change (for example the bank shifted the execution date). The standing order is active.
IL060311140000000436488PATCIn progressPartially accepted — a multi-level SCA is required and some, but not all, approvals are done.
IL120311140000000436283RCVDIn progressReceived, awaiting processing.
IL490311240000000272604RJCTTerminalThe bank rejected the standing order (also the result if SCA is not completed in time).
IL060311140000000436682CANCTerminalThe standing order was cancelled.
📘

debtorAccountType must be "iban" for the open-finance-sandbox provider, and the creditor account must differ from the debtor account.

Create a periodic payment

Send an authenticated POST to /pay/open-banking-init with periodicPaymentInformation. The call requires the create:payments scope.

curl --request POST \
  --url https://api.open-finance.ai/v2/pay/open-banking-init \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "providerId": "open-finance-sandbox",
    "includeFakeProviders": true,
    "psuId": "000000000",
    "periodicPaymentInformation": {
      "amount": 250,
      "currency": "ILS",
      "description": "Monthly rent",
      "debtorAccountType": "iban",
      "debtorAccountNumber": "IL070311140000000435694",
      "creditorAccountType": "iban",
      "creditorAccountNumber": "IL900311140000000111111",
      "creditorName": "Landlord Ltd",
      "startDate": "2030-01-01",
      "endDate": "2031-01-01",
      "frequency": "Monthly",
      "dayOfExecution": "1"
    }
  }'
const res = await fetch("https://api.open-finance.ai/v2/pay/open-banking-init", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${accessToken}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    providerId: "open-finance-sandbox",
    includeFakeProviders: true,
    psuId: "000000000",
    periodicPaymentInformation: {
      amount: 250,
      currency: "ILS",
      description: "Monthly rent",
      debtorAccountType: "iban",
      debtorAccountNumber: "IL070311140000000435694", // -> ACTC (active)
      creditorAccountType: "iban",
      creditorAccountNumber: "IL900311140000000111111",
      creditorName: "Landlord Ltd",
      startDate: "2030-01-01",
      endDate: "2031-01-01",
      frequency: "Monthly",
      dayOfExecution: "1",
    },
  }),
});

const { paymentId, status } = await res.json();
// status === "ACTC"

The response returns the created payment id and its standing-order status:

{
  "paymentId": "01J9X8Z2K4P7QF0V2N6M3B5A1C",
  "status": "ACTC",
  "scaOAuth": "https://.../?state=01J9X8Z2K4P7QF0V2N6M3B5A1C"
}

Swap debtorAccountNumber for IL490311240000000272604 and the same request returns "status": "RJCT" instead — that is the whole point of the sandbox.

Required & notable fields

providerId, includeFakeProviders, and psuId are top-level. Every other field below lives inside the periodicPaymentInformation object.

FieldNotes
providerId (top level)Use "open-finance-sandbox".
includeFakeProviders (top level)Must be true — the sandbox is a test provider.
amountGreater than 0.
currency"ILS".
descriptionRequired.
debtorAccountNumber / debtorAccountTypeRequired. Use a periodic sandbox account with type "iban".
creditorAccountNumber + creditorName, or merchantIdProvide the creditor explicitly or resolve it from a merchant. Must differ from the debtor account.
startDateISO date, tomorrow or later (the start date must be strictly in the future).
endDateOptional. If omitted the standing order is open-ended. When provided it must be at least one full frequency period after startDate (Monthly → +1 month, Quarterly → +3 months, Annual → +1 year), so the order always spans at least two occurrences.
frequencyOne of Monthly, Quarterly, Annual.
dayOfExecutionOptional, 131 (31 means the last day of the month — ultimo).
executionRuleOptional, following or preceding — how to shift an execution that lands on a weekend or bank holiday.

Check the status

Read the standing order back at any time with GET /payments/{paymentId}/status (scope read:payments). For sandbox payments this returns the stored payment as-is.

curl --request GET \
  --url https://api.open-finance.ai/v2/payments/01J9X8Z2K4P7QF0V2N6M3B5A1C/status \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'

Override the status

To walk a standing order through additional transitions (for example RCVDACTC, or PATCACTC once all SCAs complete), update it directly with PATCH /payments/sandbox/{paymentId} (scope create:payments). This endpoint only works on sandbox payments.

curl --request PATCH \
  --url https://api.open-finance.ai/v2/payments/sandbox/01J9X8Z2K4P7QF0V2N6M3B5A1C \
  --header 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{ "status": "ACTC" }'

Standing-order status reference

These are the transaction statuses a standing order can carry, per the spec (see Spec alignment).

StatusGroupDescription
RCVDIn progressReceived by the bank, not yet processed.
PATCIn progressPartially accepted, technically correct — multi-level SCA, some but not all approvals done.
ACTCActiveAccepted, technical validation passed — the standing order is set up. The typical end status for periodic payments.
ACWCActiveAccepted with change (for example a changed execution date).
RJCTTerminalRejected by the bank (also when a required SCA is not completed in time).
CANCTerminalCancelled.

Spec alignment

The statuses above are the subset of the ISO 20022 / Berlin Group transaction statuses that the Bank of Israel "Open Banking IL" Implementation Guidelines v1.8 (NextGenPSD2 XS2A Framework) permit for standing orders:

  • The end status of a periodic payment initiation is ACTC (§4.14.1 — periodic payments are not executed immediately, so they finish technical validation rather than settlement). ACCP is mentioned by the framework but is not used in Israel.
  • CANC is explicitly valid for future-dated and recurring/standing payments (§14.13).
  • A standing order that does not complete its required SCA (including multi-level SCA) becomes RJCT (§5.4).

Statuses intentionally not offered for periodic payments:

  • PART — used only for bulk payments (§14.13).
  • PDNG/PENDING, ACCP, ACWP — not used in Israel (§14.13).
  • ACSC, ACSP, ACCC, ACFC — settlement/funds-check statuses of an executed transfer, not of a standing-order initiation.

Next steps

  • Repeat the create call with each periodic sandbox debtor account to cover every status your integration must handle.
  • Point your webhook/notification handler at the sandbox to confirm you receive the status you expect.
  • When your flows pass against the sandbox, switch providerId to a real bank and drop includeFakeProviders.