Sandbox live

Sandbox testing

Take a sandbox API key through to a confirmed enrolment, then replay create and confirm.

Use sandbox hosts and fictional student data only. Never paste a real key or a production student record.

What you will do

  1. Receive a sandbox provider key from StudentPay
  2. Use the sandbox base URL
  3. Generate a stable provider_order_id
  4. Create a checkout
  5. Redirect the payer to setup_url
  6. Complete the GoCardless sandbox BECS NZ flow
  7. Poll GET until direct_debit.setup_complete is true
  8. Confirm with the required declarations
  9. Read the confirmed status and agreement references
  10. Replay create and confirm to prove idempotency

Setup complete is not Authorised. Mandate active can happen later and is not required for confirm. After confirm, Salesforce creates the payment schedule and owns collection. Your integration does not submit payments.

Kind Who Credential
API Your backend Authorization: Bearer <YOUR_API_KEY>
Browser Payer Setup URL token only — never your API key

1. Authenticate

StudentPay issues a sandbox key and a provider_code. Examples use SANDBOX_DEMO. Keep the key on your server.

Authorization: Bearer <YOUR_API_KEY>
Content-Type: application/json

2. Check sandbox

API — no key

GET https://sandbox-api.studentpay.co.nz/v1/environment
{
  "success": true,
  "environment": "sandbox",
  "api_base_url": "https://sandbox-api.studentpay.co.nz",
  "payment_processor": "gocardless",
  "payment_processor_status": "configured",
  "readiness": {
    "ready_for_api_calls": true
  }
}

3. Create a checkout

Generate a provider_order_id you can reuse on retries. Do not change the logical enrolment when you retry.

If StudentPay has configured your provider as catalogue-authoritative, send course.course_code instead of inventing price and instalment maths. See Enrolment Integration.

The sandbox walkthrough below uses SANDBOX_DEMO, which remains on the legacy client-supplied plan contract when course.course_code is omitted.

API — your backend

POST https://sandbox-api.studentpay.co.nz/v1/provider-checkouts
Authorization: Bearer <YOUR_API_KEY>
Content-Type: application/json
Idempotency-Key: DEMO-ENROLMENT-1001
{
  "provider": {
    "provider_code": "SANDBOX_DEMO",
    "provider_order_id": "DEMO-ENROLMENT-1001"
  },
  "student": {
    "first_name": "Alex",
    "last_name": "Student",
    "email": "alex.student@example.com"
  },
  "course": {
    "course_name": "Example Certificate"
  },
  "pricing": {
    "course_price": 1834.25,
    "amount_to_finance": 1834.25,
    "upfront_payment": 0
  },
  "plan": {
    "payment_type": "interest_free_payment_plan",
    "payment_frequency": "Weekly",
    "number_of_instalments": 74,
    "instalment_amount": 25,
    "final_instalment_amount": 9.25,
    "first_payment_date": "2026-10-01"
  }
}

provider.provider_code must match the key.

StudentPay validates integer-cent maths. This example is a residual plan: 73 × $25.00 + 1 × $9.25 = $1,834.25. See Payment Plans.

Create response

{
  "success": true,
  "idempotent_replay": false,
  "provider": {
    "provider_code": "SANDBOX_DEMO",
    "provider_order_id": "DEMO-ENROLMENT-1001"
  },
  "records": {
    "contact_id": "003XXXXXXXXXXXX",
    "opportunity_id": "006XXXXXXXXXXXX",
    "dda_id": "a0XXXXXXXXXXXXX"
  },
  "checkout": {
    "checkout_id": "SANDBOX_DEMO-1720000000000-AB12CD34",
    "status": "direct_debit_setup_required",
    "requires_direct_debit": true
  },
  "direct_debit": {
    "setup_complete": false,
    "dda_id": "a0XXXXXXXXXXXXX",
    "setup_url": "https://sandbox-api.studentpay.co.nz/api/dd-setup?token=<setup-token>",
    "token": "<setup-token>"
  }
}

Keep checkout.checkout_id, records.opportunity_id, direct_debit.dda_id, direct_debit.setup_url, and direct_debit.token (this is checkout.checkout_token on confirm).

setup_complete is false here. That is expected.

4. Redirect the payer to hosted setup

Browser — not your API key

Open direct_debit.setup_url as a redirect or popup. The payer completes BECS NZ bank details on GoCardless using GoCardless sandbox test details. This is not a StudentPay JSON API call.

Do not send Authorization: Bearer <YOUR_API_KEY> from the browser.

5. Return, then wait for setup complete

GoCardless returns the browser to StudentPay. Treat any popup message as a hint only.

API — your backend

GET https://sandbox-api.studentpay.co.nz/v1/provider-checkouts/SANDBOX_DEMO-1720000000000-AB12CD34
Authorization: Bearer <YOUR_API_KEY>

Wait until direct_debit.setup_complete is true:

{
  "success": true,
  "checkout": {
    "checkout_id": "SANDBOX_DEMO-1720000000000-AB12CD34",
    "status": "direct_debit_setup_required"
  },
  "direct_debit": {
    "setup_complete": true,
    "billing_request_status": "fulfilled",
    "mandate_status": "pending_submission",
    "authorisation_status": "Customer In Progress",
    "authorised": false,
    "dda_id": "a0XXXXXXXXXXXXX"
  }
}

You may confirm while mandate_status is pending_submission or submitted and authorised is false.

6. Confirm enrolment

API — your backend

POST https://sandbox-api.studentpay.co.nz/v1/provider-checkouts/SANDBOX_DEMO-1720000000000-AB12CD34/confirm
Authorization: Bearer <YOUR_API_KEY>
Content-Type: application/json
{
  "provider": {
    "provider_code": "SANDBOX_DEMO",
    "provider_order_id": "DEMO-ENROLMENT-1001"
  },
  "checkout": {
    "checkout_id": "SANDBOX_DEMO-1720000000000-AB12CD34",
    "checkout_token": "<setup-token>",
    "opportunity_id": "006XXXXXXXXXXXX",
    "dda_id": "a0XXXXXXXXXXXXX"
  },
  "payment": {
    "payment_method": "studentpay_payment_plan",
    "first_payment_date": "2026-10-01",
    "deposit_confirmed": true
  },
  "declarations": {
    "payment_plan_accepted": true,
    "information_confirmed": true,
    "privacy_consent_accepted": true
  }
}

Always include {checkoutId} in the path. Use direct_debit.token from create. All three declarations and deposit_confirmed must be true. Confirm does not collect money. After confirm, Salesforce originates any initial-payment Charge_Schedule and the existing Direct Debit processor collects it.

Confirm response

{
  "success": true,
  "checkout": { "status": "confirmed", "id": "SANDBOX_DEMO-1720000000000-AB12CD34" },
  "enrolment": { "status": "complete" },
  "direct_debit": {
    "setup_complete": true,
    "mandate_status": "pending_submission"
  },
  "agreement": {
    "id": "a0JXXXXXXXXXXXX",
    "number": "PPA-000001",
    "pdf_generated": true
  },
  "already_confirmed": false
}

7. Replay safely

POST create again with the same provider_order_id / Idempotency-Key. Expect idempotent_replay: true and no second enrolment.

POST confirm again. Expect already_confirmed: true and the same agreement references.

Done

Enrolment is complete for this API when checkout.status is confirmed and enrolment.status is complete.

What happens later, outside this API:

  • Mandate may become active / Authorised
  • Salesforce creates the payment schedule
  • Salesforce owns collection

Next