Quickstart
Integrate an education-provider enrolment wizard with StudentPay.
This guide covers the two flows used by Academy Australia–style pages:
- Pay Now — full course fee by card (Pinch Capture.js → create checkout)
- Payment plan — create checkout → hosted DDA → confirm enrolment
Choose your path
| Step | Pay Now (card) | Payment plan (direct debit) |
|---|---|---|
| 1. Create checkout | payment_type: upfront_payment + card_payment.token |
payment_type: interest_free_payment_plan |
| 2. Collect bank authority | Not used | Open / embed direct_debit.setup_url |
| 3. Finish enrolment | In your UI: accept the education provider Terms & Conditions, then treat card_payment.success on create as payment complete. Do not call StudentPay confirm (that API requires a DDA). |
After DDA authorised: POST …/confirm with declarations + dda_id |
| 4. Done when | Card charged; Opportunity created with Paid Upfront / Payment Processing; no DDA and no Payment Plan Agreement | Opportunity Payment Plan Signed + Payment Plan Agreement PDF |
See Authentication and Environments.
0. Confirm sandbox
curl https://sandbox-api.studentpay.com.au/v1/environment
Expect "environment": "sandbox", "pinch_mode": "test", and pinch_publishable_key (publishable by design for Capture.js).
Your API key’s provider_code must match the body (sandbox demos often use SANDBOX_DEMO).
1. Authenticate
Authorization: Bearer <PROVIDER_API_KEY>
Content-Type: application/json
Path A — Pay Now (full card payment)
A1. Tokenise the card in the browser
Never POST raw card numbers to StudentPay.
const capture = new Pinch.Capture({
publishableKey: pinchPublishableKey // from GET /v1/environment
});
const result = await capture.createToken({
sourceType: "credit-card",
cardNumber: "4242424242424242",
expiryMonth: "11",
expiryYear: "2027",
cvc: "123",
cardHolderName: "Jamie Nguyen"
});
const token = result.token;
Load Capture.js from https://cdn.getpinch.com.au/capturejs/pinch.capture.v2.js.
Sandbox test cards
Any future expiry + any CVC:
| Card number | Type |
|---|---|
4242424242424242 |
Visa (AU) |
4000000360000006 |
Visa (AU) |
378282246310005 |
AMEX (AU) |
5105105105105100 |
Mastercard |
Do not use placeholder numbers such as 1234123412341234.
A2. Create checkout with the token
POST /v1/provider-checkouts
Idempotency-Key: AA-ENROLMENT-67890
{
"provider": {
"provider_code": "SANDBOX_DEMO",
"provider_order_id": "AA-ENROLMENT-67890",
"provider_account_id": "001XXXXXXXXXXXX"
},
"student": {
"first_name": "Jamie",
"last_name": "Nguyen",
"email": "jamie.nguyen@example.com"
},
"course": {
"course_name": "Advanced Full Stack Developer Accelerator"
},
"pricing": {
"course_price": 4995,
"amount_to_finance": 4995,
"upfront_payment": 4995
},
"plan": {
"payment_type": "upfront_payment",
"payment_frequency": "Upfront",
"number_of_instalments": 1,
"instalment_amount": 4995,
"first_payment_date": "2026-08-18"
},
"card_payment": {
"token": "pt_test_xxxxxxxx",
"amount_to_charge_now": 4995,
"payment_purpose": "card"
}
}
plan.* remains required. pricing.amount_to_finance must be > 0 — for full Pay Now, send the course fee.
Schemas: Create a provider checkout.
A3. Finish enrolment in your UI (not StudentPay confirm)
Accept the education provider Terms & Conditions in your checkout UI.
Treat card_payment.success === true on create as payment complete. Do not call confirm — it requires checkout.dda_id, and Pay Now does not create a DDA or Payment Plan Agreement.
Done when: Checkout Status Payment Processing, Authorisation Status Paid Upfront, zero Direct Debit Authorisations, zero Payment Plan Agreements.
Path B — Payment plan (direct debit)
B1. Create checkout
POST /v1/provider-checkouts
Idempotency-Key: ONFIT-ENROLMENT-12345
{
"provider": {
"provider_code": "SANDBOX_DEMO",
"provider_order_id": "ONFIT-ENROLMENT-12345",
"provider_account_id": "001XXXXXXXXXXXX"
},
"student": {
"first_name": "Alex",
"last_name": "Student",
"email": "alex.student@example.com"
},
"course": {
"course_name": "Certificate IV in Fitness"
},
"pricing": {
"course_price": 2990,
"amount_to_finance": 2490
},
"plan": {
"payment_type": "interest_free_payment_plan",
"payment_frequency": "Fortnightly",
"number_of_instalments": 20,
"instalment_amount": 124.5,
"first_payment_date": "2026-08-18"
}
}
Use direct_debit.setup_url for bank authority (hosted /api/dd-setup). Prefer Idempotency-Key — see Idempotency.
B2. Confirm enrolment
After DDA authorisation and student declarations:
POST /v1/provider-checkouts/{checkoutId}/confirm
Compatible legacy route (same body): POST /api/provider-checkout-confirm.
{
"provider": {
"provider_code": "SANDBOX_DEMO",
"provider_order_id": "ONFIT-ENROLMENT-12345"
},
"checkout": {
"checkout_id": "SANDBOX_DEMO_…",
"checkout_token": "eyJ…",
"opportunity_id": "006…",
"dda_id": "a0…"
},
"payment": {
"payment_method": "studentpay_payment_plan",
"first_payment_date": "2026-08-18",
"deposit_confirmed": true
},
"declarations": {
"payment_plan_accepted": true,
"information_confirmed": true,
"privacy_consent_accepted": true
}
}
dda_id and all three declaration booleans are required. Confirm creates the Payment Plan Agreement PDF and moves the Opportunity to Payment Plan Signed.
Always include {checkoutId} in the v1 path (or use the legacy URL). A bare /v1/provider-checkouts/confirm returns 405.
Retrieve status
GET /v1/provider-checkouts/{checkoutId}
Next
- Browse the interactive API Reference
- Understand the error envelope
- Review webhooks