Payment Plans
NZ provider checkout establishes an interest-free payment plan. Create either identifies an approved course (catalogue-authoritative providers) or describes a legacy commercial plan. StudentPay does not collect the instalments on that call.
After confirm, Salesforce creates the schedule and owns collection.
Fields
| Field | Required | Meaning |
|---|---|---|
course.course_code |
Catalogue-authoritative providers | Approved StudentPay product/course identifier |
pricing.course_price |
Legacy; optional match on catalogue | Full course price. Exact cents, greater than zero |
pricing.upfront_payment |
No | Initial payment on the payment plan. Exact cents, ≥ 0. Omitted means 0. Confirm does not collect it; Salesforce originates a Charge_Schedule when > 0 |
pricing.amount_to_finance |
Legacy; optional match on catalogue | Amount financed. Exact cents, greater than zero. This API does not collect it |
plan.instalment_amount |
Legacy; optional match on catalogue | The regular (recurring) instalment. Exact cents, greater than zero |
plan.number_of_instalments |
Legacy; optional match on catalogue | Total count of instalments (includes the final one). Positive integer |
plan.regular_instalment_amount |
No | Optional alias for the regular instalment. When sent, must equal instalment_amount |
plan.final_instalment_amount |
No | Optional residual final instalment. Exact cents. 0 < final < instalment_amount |
plan.payment_frequency |
Legacy; constrained on catalogue | Must be an allowed frequency for the course. Omitted catalogue creates use the course default |
plan.first_payment_date |
Yes | ISO date (YYYY-MM-DD) |
plan.payment_type |
Legacy; filled on catalogue | Use interest_free_payment_plan |
Who supplies pricing
Enrolment Integration — catalogue-authoritative (OLI_NZ, BELA_NZ):
send course.course_code. StudentPay resolves price, currency, upfront,
allowed frequencies, and instalment maths, then reconciles them through the
same integer-cent calculator used for residual plans. You cannot override
those values.
Enrolment Integration — legacy: if your provider is not catalogue-authoritative
and you omit course.course_code, you calculate and supply the commercial
fields. StudentPay validates and reconciles them.
Hosted Enrolment Checkout: course data is resolved from StudentPay-controlled server configuration. The browser does not supply the authoritative course price.
See Current contract.
Validation the API enforces
Create returns 400 VALIDATION_ERROR when required fields are missing, when
money is not an exact cent amount, when plan.number_of_instalments is not a
positive integer, or when a catalogue identifier / amount is invalid.
Catalogue failures include:
- unknown
course.course_code - course belongs to another provider
- inactive course
- course not enabled for this environment (sandbox vs production)
- unsupported
plan.payment_frequency - client-supplied money or instalment count that does not match the catalogue
For plan.payment_type = interest_free_payment_plan, create also requires
equal-instalment arithmetic in integer cents:
amount_to_finance = course_price − upfront_payment
amount_to_finance = number_of_instalments × instalment_amount
upfront_payment is optional. Omitted or empty means 0.
Residual final instalment
When a plan does not divide into equal instalments, the last instalment is the
residual. Catalogue-authoritative creates derive that residual server-side.
Legacy creates may supply it with plan.final_instalment_amount.
plan.number_of_instalments includes the final instalment. The API validates,
in integer cents:
amount_to_finance = (number_of_instalments − 1) × instalment_amount + final_instalment_amount
0 < final_instalment_amount < instalment_amount
Omitting final_instalment_amount on a legacy equal-instalment plan keeps
that contract unchanged.
PSY101 (and the generic residual sandbox example) uses:
| Field | Value |
|---|---|
| Course price | $1,834.25 |
| Initial payment | $0.00 (no extra Charge_Schedule) |
| Amount financed | $1,834.25 |
| Regular instalment | $25.00 |
| Final instalment | $9.25 |
| Number of instalments | 74 |
| Frequency | Weekly |
73 × $25.00 + 1 × $9.25 = $1,834.25. The last instalment can differ so that principal is conserved exactly. Salesforce originates that exact final Charge Schedule row. The Payment Plan Agreement states the residual final instalment. Create and retrieve echo a residual-aware plan block.
Invalid commercial payloads fail before StudentPay creates or updates Contact, Opportunity, DDA, agreement, or payment-processor state.
Mismatches are returned as details.invalid_fields on the existing VALIDATION_ERROR envelope (for example pricing.course_price, plan.instalment_amount, course.course_code).
Equal-instalment plans remain valid: omit final_instalment_amount and keep number_of_instalments × instalment_amount = amount_to_finance.
Confirm body
Confirm repeats payment.first_payment_date and requires payment.deposit_confirmed: true and payment.payment_method (use studentpay_payment_plan). Those fields record acceptance. Confirm does not collect the initial payment.
After confirm
Do not call a payments API. There isn’t one on this contract. Salesforce creates the schedule from the confirmed plan, including one initial-payment Charge_Schedule when upfront_payment > 0. First collection is not the confirm response; the existing scheduled-payment processor submits due Direct Debits.
Create and GET include plan.initial_payment and plan.upfront_payment (same cents), plan.amount_to_finance, plan.number_of_instalments, plan.instalment_amount, and plan.first_payment_date (first regular instalment).