PaymentSchedule API
Schedule payments against existing payment agreements
The Payment Schedule API turns an authorised NPP PayTo agreement into a set-and-forget recurring payment. Instead of calling the payment initiation API for every run, you tell us the schedule details once and Azupay initiates payments on the agreement's cadence.
This guide covers the full lifecycle: create a schedule, retrieve it, and pause or resume it. Every endpoint shown extends the existing Azupay REST API and reuses the same SecretKey authentication and error model conventions you already know.
What you'll need before you startA Payment Agreement that is in
ACTIVEstate and has been authorised by the payer at their bank.
You can also view a schedule's current status, cadence, and last run directly in the Azupay dashboard — see the Schedule panel on the Payment Agreements page.
Endpoints at a glance
| Method | Path | Purpose |
|---|---|---|
POST | /v1/paymentAgreement/{paymentAgreementId}/scheduler | Create a schedule against an existing payment agreement. Amends an existing schedule. |
GET | /v1/paymentAgreement/{paymentAgreementId}/scheduler | Retrieve a schedule by payment agreement ID. |
To search for payment initiations, refer to our existing paymentInitiation API.
Create a Payment Schedule
Create a schedule by POSTing the agreement ID with the schedule details:
POST https://api.azupay.com.au/v1/paymentAgreement/{paymentAgreementId}/scheduler
Authorization: SECR_MYBUSINESSID_nR2duCGXlqWSuYJG
Content-Type: application/json{
"PaymentScheduler": {
"status": "ACTIVE",
"frequency": "MONTHLY",
"amount": "89.95",
"startDate": "2026-08-01",
"endDate": "2027-06-01",
"timezone": "Australia/Sydney"
}
}Request fields
| Field | Required | Description |
|---|---|---|
status | yes | Status of this schedule. Must be ACTIVE when creating a schedule for the first time. |
frequency | yes | Frequency of the scheduled runs (ONCE, WEEKLY, FORTNIGHTLY, MONTHLY, ANNUAL). Must match the agreement's frequency, with one exception each way: an ADHOC agreement accepts any of them, and ONCE is only valid on an ADHOC agreement. See One-off payments below. |
amount | yes | Run amount in AUD as a string, e.g. "89.95". Must fit inside the agreement's per-payment and per-period caps. |
startDate | yes | First run date, YYYY-MM-DD. Must be strictly after today in the schedule's timezone. A ONCE schedule is the exception - it may be dated today. |
endDate | no | Last permitted run date, YYYY-MM-DD. Omit for an open-ended schedule, and omit it for a ONCE schedule - a single run has no cadence to bound. |
timezone | yes | IANA name (e.g. Australia/Sydney, Australia/Perth, UTC). No implicit default. |
What is not on this callNo retry parameters, the scheduler does not retry for hard failures. No
additionalDetailsblock - schedule creation is a back-office action, not a payer-initiated payment. No callback URL on the schedule resource - run outcomes ride on your existing Payment Initiation webhook.
Successful response - 201 Created
201 Created{
"PaymentScheduler": {
"paymentAgreementId": "aa340b79a04571f989bed2f8d0f771b4",
"status": "ACTIVE",
"frequency": "MONTHLY",
"amount": "89.95",
"startDate": "2026-08-01",
"endDate": "2027-06-01",
"timezone": "Australia/Sydney"
},
"PaymentSchedulerStatus": {
"version": 1,
"createdDatetime": "2026-05-18T04:33:12.045Z",
"updatedDatetime": "2026-06-23T02:42:32.753Z"
}
}Validation Errors - 4xx
4xxSee down below for a full list of 4xx errors and their corresponding messages.
{
"message": "version does not match the current scheduler version",
"details": {
"failureCode": "AZP3.8",
"failureReason": "version does not match the current scheduler version"
}
}failureCode | HTTP | failureReason |
|---|---|---|
ERR0.03 | 400 | Request validation failed. Message can vary. |
AZP3.1 | 400 | Payment Agreement is not active or does not exist |
AZP3.2 | 400 | Start date must be future-dated - at least one day after today in the scheduler's timezone (recurring only; ONCE may run today) |
AZP3.3 | 400 | End date must be equal to or after start date |
AZP3.4 | 400 | Amount exceeds the agreement's per-payment cap |
AZP3.5 | 400 | Frequency mismatch between agreement and scheduler - including ONCE against an agreement whose frequency is not ADHOC |
AZP3.6 | 400 | Timezone is not a valid IANA name |
AZP3.9 | 400 | Schedule date falls beyond the payment agreement's end date |
AZP4.2 | 409 | A non-terminal scheduler is already attached to this agreement |
AZP4.3 | 400 | The target status you provide must be ACTIVE |
AZP4.14 | 404 | Payment agreement was not found (also returned for a missing agreement id or a cross-client ownership mismatch) |
One active schedule per agreementOnly one schedule can be created against one agreement. By calling POST against the same payment agreement, it will be amended instead.
How cadence is anchored
The cadence anchor is derived from startDate in combination with the agreement's frequency. This applies to recurring schedules only - a ONCE schedule has no cadence and runs on startDate alone.
- Weekly - same day-of-week as
startDate, every week. - Fortnightly -
startDate, then every 14 days. - Monthly -
startDate.dayevery month. IfstartDate.dayis 29, 30, or 31, the schedule executes on the last day of every month instead - so February is never silently skipped. - Annually - same month and day as
startDate, every year.Feb 29resolves to the last day of February each year.
No backfill - schedule resumes from next occurrenceIf an execution is missed for any reason, the schedule resumes from its next scheduled occurrence; missed executions are not replayed. Azupay will never initiate two payments for the same scheduled run.
One-off payments - ONCE on an ADHOC agreement
ONCE on an ADHOC agreementNot every agreement is a recurring one. An agreement created with a frequency of ADHOC has no fixed cadence - the payer has authorised you to collect as needed, within the agreement's caps. When you want Azupay to initiate one of those collections on a nominated date, without your systems having to call the payment initiation API on the day, attach a schedule with a frequency of ONCE.
ONCE requires an ADHOC agreement. The rule does not run both ways: because an ADHOC agreement has no cadence of its own, it accepts any scheduler frequency - ONCE for a single collection, or a recurring frequency if you would rather put a regular cadence over it. Every other agreement must be matched exactly.
| Agreement frequency | Scheduler frequency | Result |
|---|---|---|
ADHOC | ONCE | Accepted - one payment on startDate |
ADHOC | WEEKLY, FORTNIGHTLY, MONTHLY, ANNUAL | Accepted - runs on the cadence you choose |
WEEKLY, FORTNIGHTLY, MONTHLY, ANNUAL | ONCE | Rejected - AZP3.5 |
WEEKLY, FORTNIGHTLY, MONTHLY, ANNUAL | A recurring frequency other than its own | Rejected - AZP3.5 |
On an ADHOC agreement the schedule is what sets the cadence, since the agreement does not carry one.
Creating a one-off schedule
Everything else on the call is unchanged - same endpoint, same envelope, same authentication:
POST https://api.azupay.com.au/v1/paymentAgreement/{paymentAgreementId}/scheduler
Authorization: SECR_MYBUSINESSID_nR2duCGXlqWSuYJG
Content-Type: application/json{
"PaymentScheduler": {
"status": "ACTIVE",
"frequency": "ONCE",
"amount": "250.00",
"startDate": "2026-09-15",
"timezone": "Australia/Sydney"
}
}startDate is simply the day the payment runs, and endDate is left out altogether - there is no recurrence for it to bound.
AONCEschedule can be dated today
ONCEis the only frequency that may carry today's date in the schedule's timezone. WhenstartDateis today, the payment is initiated within 10 minutes rather than waiting for the next morning run. Every other frequency must be dated at least one day ahead, or the request is rejected withAZP3.2.
Successful response - 201 Created
201 Created{
"PaymentScheduler": {
"paymentAgreementId": "b71e04c3f2a94d5eab6c8f1207d3e5a9",
"status": "ACTIVE",
"frequency": "ONCE",
"amount": "250.00",
"startDate": "2026-09-15",
"timezone": "Australia/Sydney"
},
"PaymentSchedulerStatus": {
"version": 1,
"createdDatetime": "2026-08-27T23:14:06.512Z"
}
}After the one-off payment has run
Once the single payment has been initiated, the schedule moves to INACTIVE. The outcome reaches you on your existing Payment Initiation webhook, exactly as it would for an ad-hoc payment your own systems initiated.
The schedule is dormant rather than finished. To collect again on the same ADHOC agreement, amend it back to ACTIVE with a new startDate and amount, quoting the current version from your most recent GET:
{
"PaymentScheduler": {
"version": 2,
"status": "ACTIVE",
"frequency": "ONCE",
"amount": "180.00",
"startDate": "2026-10-02",
"timezone": "Australia/Sydney"
}
}There is still only ever one schedule per agreement, so each subsequent one-off collection reuses this same resource. The full payload and a matching version are required, as they are for any amendment - see Amend an existing Payment Schedule below.
Retrieve a Payment Schedule
GET https://api.azupay.com.au/v1/paymentAgreement/{paymentAgreementId}/scheduler
Authorization: SECR_MYBUSINESSID_nR2duCGXlqWSuYJFReturns the request payload alongside the current state (status, cadence, last run).
Successful response - 200 OK
200 OK{
"PaymentScheduler": {
"paymentAgreementId": "aa340b79a04571f989bed2f8d0f771b4",
"status": "ACTIVE",
"frequency": "MONTHLY",
"amount": "89.95",
"startDate": "2026-08-01",
"endDate": "2027-06-01",
"timezone": "Australia/Sydney"
},
"PaymentSchedulerStatus": {
"version": 2,
"lastRunDatetime": "2026-06-01T04:33:12.045Z",
"updatedDatetime": "2026-07-03T01:12:58.089Z",
"createdDatetime": "2026-05-18T04:33:12.045Z"
}
}Amend an existing Payment Schedule
To amend an existing schedule, use the original POST /paymentAgreement/{paymentAgreementId}/scheduler
Semantics
- If no schedule exists for the
paymentAgreementId, one will be created. - If a schedule already exists, the full payload is required to amend a schedule
- There is only ever one schedule per payment agreement.
- Changes apply to future scheduled payments only.
- When amending,
versionis required and must match the currentversionreturned by the most recent GET or POST. If the version does not match, the amendment is rejected with409 Conflict- this prevents concurrent calls from silently overwriting each other.
Amendable fields
You must provide the version you are amendingVersion must be provided when amending a schedule. It should be the same version from the most current GET response. Once updated, the version will then be incremented.
| Field | Notes |
|---|---|
status | Switch between ACTIVE and INACTIVE. |
amount | New run amount in AUD. Must still fit inside the agreement's caps. |
startDate | Reschedules the cadence anchor. Must be strictly after today in the schedule's timezone and cannot be before the next pending run date. |
endDate | Extend, shorten, or remove the end boundary. |
frequency | Must match the frequency permitted by the payment agreement. |
timezone | Valid IANA timezone name. |
version | The version of the schedule you are currently amending. |
The full payload is required for amendmentsTo clear an optional field (e.g.
endDate), send it explicitly asnull.
Example - amending amount and end date
The full payload is required to amend a schedule.
POST https://api.azupay.com.au/v1/paymentAgreement/{paymentAgreementId}/scheduler
Authorization: SECR_MYBUSINESSID_nR2duCGXlqWSuYJF
Content-Type: application/json{
"PaymentScheduler": {
"version": 2,
"status": "ACTIVE",
"frequency": "MONTHLY",
"amount": "99.95",
"startDate": "2026-08-01",
"endDate": "2029-06-01",
"timezone": "Australia/Sydney"
}
}Successful response - 200 OK
200 OK{
"PaymentScheduler": {
"paymentAgreementId": "aa340b79a04571f989bed2f8d0f771b4",
"status": "ACTIVE",
"frequency": "MONTHLY",
"amount": "99.95",
"startDate": "2026-08-01",
"endDate": "2029-06-01",
"timezone": "Australia/Sydney"
},
"PaymentSchedulerStatus": {
"version": 3,
"lastRunDatetime": "2026-06-01T04:33:12.045Z",
"createdDatetime": "2026-05-18T04:33:12.045Z",
"updatedDatetime": "2026-05-28T01:12:44.901Z"
}
}Example - pausing a schedule
The full payload is required to amend a schedule.
POST https://api.azupay.com.au/v1/paymentAgreement/{paymentAgreementId}/scheduler
Authorization: SECR_MYBUSINESSID_nR2duCGXlqWSuYJF
Content-Type: application/json{
"PaymentScheduler": {
"version": 3,
"status": "INACTIVE",
"frequency": "MONTHLY",
"amount": "99.95",
"startDate": "2026-08-01",
"endDate": "2029-06-01",
"timezone": "Australia/Sydney"
}
}Successful response - 200 OK
200 OK{
"PaymentScheduler": {
"paymentAgreementId": "aa340b79a04571f989bed2f8d0f771b4",
"status": "INACTIVE",
"frequency": "MONTHLY",
"amount": "99.95",
"startDate": "2026-08-01",
"endDate": "2029-06-01",
"timezone": "Australia/Sydney"
},
"PaymentSchedulerStatus": {
"version": 4,
"lastRunDatetime": "2026-06-01T04:33:12.045Z",
"createdDatetime": "2026-05-18T04:33:12.045Z",
"updatedDatetime": "2026-05-28T01:12:44.901Z"
}
} Schedule Status & Agreement Status
The Payment Agreement status will be synced with the Payment Schedule status automatically.
Allowed transitions
| From | To | Effect |
|---|---|---|
ACTIVE | INACTIVE | Suspends further runs. The underlying agreement is untouched. |
INACTIVE | ACTIVE | Resumes the schedule from its next scheduled run. Runs missed during the pause are not back-filled. |
A ONCE schedule that has already run has no next scheduled run, so reactivating it also requires a new startDate.
Validation Errors - 4xx
4xx See down below for a full list of 4xx errors and their corresponding messages.
{
"message": "version does not match the current scheduler version",
"details": {
"failureCode": "AZP3.8",
"failureReason": "version does not match the current scheduler version"
}
}failureCode | HTTP | failureReason |
|---|---|---|
ERR0.03 | 400 | Request validation failed. Message can vary. |
AZP3.1 | 400 | Payment Agreement is not active or does not exist |
AZP3.2 | 400 | Start date must be future-dated - at least one day after today in the scheduler's timezone (recurring only; ONCE may run today) |
AZP3.3 | 400 | End date must be equal to or after start date |
AZP3.4 | 400 | Amount exceeds the agreement's per-payment cap |
AZP3.5 | 400 | Frequency mismatch between agreement and scheduler - including ONCE against an agreement whose frequency is not ADHOC |
AZP3.6 | 400 | Timezone is not a valid IANA name |
AZP3.7 | 400 | version is required when amending an existing scheduler |
AZP3.8 | 409 | version does not match the current scheduler version |
AZP3.9 | 400 | Schedule date falls beyond the payment agreement's end date |
AZP4.14 | 404 | Payment agreement was not found (also returned for a cross-client ownership mismatch) |
Schedule lifecycle
The schedule has two states: ACTIVE & INACTIVE
Merchant-driven transitions
Merchants can change the status of the schedule via POST /paymentAgreement/{paymentAgreementId}/scheduler
Agreement-driven transitions (automatic - no API call needed)
The schedule status is only affected when the underlying agreement is cancelled - regardless of how or by whom. Payments are attempted as normal while the agreement is paused or suspended by the payer or bank. When a cancellation is received, the schedule moves to INACTIVE only after the latest payment initiation attempt has completed.
| Trigger | Result |
|---|---|
| Payer cancels the agreement | Schedule → INACTIVE |
| Merchant cancels the agreement via API | Schedule → INACTIVE |
| Agreement expires | Schedule → INACTIVE |
| Bank cancels or revokes the agreement | Schedule → INACTIVE |
Completion
When endDate is reached, the schedule moves to INACTIVE. A ONCE schedule moves to INACTIVE as soon as its single payment has been initiated, and can be amended back to ACTIVE with a new startDate to collect again.
You don't get schedule-specific webhooksBy design, the schedule does not emit its own callbacks. Run outcomes flow through the existing Payment Initiation webhook. Agreement-driven status changes flow through the existing Payment Agreement webhook. The schedule resource simply mirrors what those events already tell you.
Webhook behaviour
The schedule does not introduce a new webhook channel. The two existing webhooks carry everything you need:
| Webhook | What it tells you |
|---|---|
PaymentInitiationStatusEvent | One event per run attempt - settlement reference, success or failure code. Same shape as any ad-hoc payment. |
PaymentAgreementStatusEvent | Tells you when the payer or bank cancels the agreement - which in turn sets the schedule to INACTIVE. |
Things to keep in mind
- No automatic retries. The schedule initiates each run once. To chase a failed collection, drive it from your own systems - for example by creating a fresh ad-hoc payment under the same agreement.
- Schedule run time: The schedule would run in the morning of the day that is programmed to run according to the provided timezone.
- No schedule-specific webhooks. Use the Payment Initiation and Payment Agreement webhooks you already consume.
- Missed runs during a pause are not back-filled. Runs that fall during a paused window are skipped; the schedule picks up at the next scheduled date when resumed.
- End-of-month handling. A monthly schedule starting on the 29th, 30th, or 31st runs on the last day of every month thereafter - by design, so shorter months like February are never silently skipped.
- One-off collections use
ONCE.ONCEis only accepted on anADHOCagreement, though anADHOCagreement will equally take a recurring frequency. AONCEschedule runs a single payment onstartDate, then goesINACTIVE; amend it with a newstartDateto collect again. Dating it today initiates the payment within 10 minutes.
Updated 14 days ago
