Current contract
This page states the NZ Enrolment contract as it works today. It is not a roadmap and it does not promise delivery dates.
Catalogue / commercial authority
StudentPay owns the money for catalogue-authoritative providers.
Hosted Enrolment Checkout
Course and commercial values are resolved from StudentPay-controlled server configuration. The browser is not the source of truth for course price.
Enrolment Integration API
There are two create modes.
Catalogue-authoritative (OLI_NZ, BELA_NZ today):
- You must send an approved
course.course_code - StudentPay resolves provider, product, price, currency, upfront, allowed frequencies, and instalment maths
- You may send
plan.payment_frequencyonly when the product allows more than one frequency (today OLI and Bela courses are Weekly) plan.first_payment_dateremains a permitted client preference- If you also send
pricing.*or plan amounts, they must match the catalogue in integer cents or create returns400VALIDATION_ERROR
Legacy (other providers, for example SANDBOX_DEMO, while they omit
course.course_code):
- You still supply
pricing.*andplan.* - StudentPay requires exact-cent amounts and validates plan arithmetic, including an optional residual final instalment
- Invalid maths is refused before financial records are created
Any provider that does send course.course_code is fail-closed against
the StudentPay catalogue, including unknown codes and codes that belong to
another provider.
Provider identity remains the API key / PIC. provider.provider_code cannot
select another provider.
Initial payment
Create stores pricing.upfront_payment as Opportunity Upfront_Payment__c.
Confirm still requires payment.deposit_confirmed: true as a declaration.
Confirm does not submit that amount.
When the stored initial payment is greater than zero, Salesforce origination
creates one additional Charge_Schedule (Frequency Once Off) due on the
confirmation date. The existing scheduled-payment processor then submits it
through the existing GoCardless Direct Debit path after enrolment.
Paid_To_Date__c does not include that amount until the Direct Debit settles.
Create and GET echo the same cents as plan.initial_payment and
plan.upfront_payment. That is an alias, not a second monetary authority.
plan.number_of_instalments remains the regular instalment count.
A $0 initial payment (for example OLI PSY101) creates no extra
Charge_Schedule and no initial Payment_Attempt.
Pay in Full by card (Stripe) is not live in Production. The Enrolment
Integration API can implement payment_option: pay_in_full behind environment,
PIC, and catalogue gates, but that path is not certified and must not be
treated as part of the current Production enrolment product.
Outbound webhooks
The NZ API can emit signed outbound events:
checkout.createdcheckout.confirmedagreement.generated
That is a code capability. Delivery also requires StudentPay to configure a destination URL and signing secret for the environment.
Until that configuration exists, GET /v1/environment may show
readiness.webhook_destinations_configured: false. Create, GET, and confirm
still succeed. Poll GET for status.
Do not assume live provider webhook delivery is generally available.
Details: Webhooks.
Idempotency vs changed payloads
Retries that reuse the same provider_order_id (and optional
Idempotency-Key) return the existing checkout when the canonical enrolment
intent is unchanged. They do not create a second Opportunity, DDA,
agreement, or schedule.
Canonical intent is the server-resolved course name, amounts, instalment, count, frequency, and first payment date. JSON key order does not matter.
A retry with the same order id and a materially different canonical intent
returns 409 IDEMPOTENCY_CONFLICT. It does not overwrite the original
enrolment.
Supported usage: reuse the original logical enrolment for the same
provider_order_id. Do not reuse an order id to represent a different course,
price, or plan.
Details: Idempotency.
Direct debit at enrolment
Enrolment creates a GoCardless BECS NZ mandate flow. Confirm does not collect the first regular instalment or any initial payment. After confirm, Salesforce originates Charge_Schedule rows and the existing scheduled-payment processor submits due Direct Debits.
Confirm when direct_debit.setup_complete is true. Mandate
pending_submission or submitted is enough. Authorised / active can
happen later.
Production certification
Hosted Enrolment Checkout has completed NZ production certification.
Enrolment Integration’s reusable /v1 machine is sandbox-certified. A
provider-owned frontend (your SIS/website, not StudentPay-hosted screens) is
what remains to finish Integration production certification for that provider.
StudentPay coordinates Production certification. Do not create an unsolicited Production enrolment.