Guides

Parties — students, payers, and inline details

Every payment intent involves at least one party — the person or entity paying — and many flows also have a separate subject (the person the payment is for, usually a student). Nexpay lets you describe these parties three different ways:

  1. Inline details — pass payer.details (and optionally subject.details) in the payment-intent body. Nothing is persisted across payments.
  2. Saved studentPOST /v2/students once, then reference by partyId on every payment for that student. Best for tuition, refunds, or any flow where the same student pays repeatedly.
  3. Saved payerPOST /v2/payers once, then reference by partyId. Best for business / corporate payers that recur across multiple students or invoices.

This guide explains when to use which, and walks the saved-document reuse flow that lets you upload an identity document once per student and reattach it to every future payment.

JSON examples show the unwrapped `data` payload

Every success response on the wire is { "data": { ... } }. The JSON examples in this guide show the inner data value — what you get after const { data } = await response.json(). List responses also include top-level hasMore, count, and sometimes total. Error responses are not wrapped — see Errors.


Pick the right shape

ScenarioUse thisWhy
One-off payer who won't pay again (random checkout, ad-hoc refund recipient)Inline payer.detailsNo persistence overhead. The payer details are written to the intent for audit and never read again.
Recurring student (tuition, instalments, multiple semesters)Saved studentPOST /v2/students then reuse partyIdLets you save identity docs once, list payment history per student, and avoid re-typing personal data.
Recurring business payer (a corporate employer, an agent paying for many students)Saved payerPOST /v2/payers then reuse partyIdMirrors students but models a non-student paying entity. Can also be a saved-document holder.
Payment-link checkout (you don't know the payer until they click)payer.role: "unknown_link_payer", no partyId, no detailsThe payer fills in their own details at submission time; Core writes them on the child intent.

A student and a payer are not mutually exclusive — for a tuition payment, the student is the subject of the payment, and the payer could be the student themselves, a parent, an agent, or a saved business payer. Both subject.partyId and payer.partyId accept saved-student or saved-payer Mongo ids.


Saved students

A student record holds personal details and identity documents for one person. It can be referenced as either the subject or the payer (or both) on any payment intent.

Create a student

curl -X POST 'https://api.nexpay.com.au/v2/students' \
  -H 'X-API-Key: nxp_ck_your-client-id:nxp_sk_your-secret' \
  -H 'Content-Type: application/json' \
  -d '{
    "firstName": "Ada",
    "lastName": "Lovelace",
    "email": "ada@example.com",
    "phone": "+61400000000",
    "dob": "1998-04-12",
    "addressLine1": "1 Macquarie St",
    "city": "Sydney",
    "state": "NSW",
    "postcode": "2000",
    "countryCode": "AU",
    "taxIdentificationNumber": "123456789"
  }'

Only firstName, lastName, and email are required. Everything else can be added later via PUT /v2/students/{_id}.

Students are identified by Mongo _id (24 hex chars). Pass this verbatim into payment-intent subject.partyId or payer.partyId.

List or look up a student

curl 'https://api.nexpay.com.au/v2/students?filter[email]=ada@example.com' \
  -H 'X-API-Key: nxp_ck_your-client-id:nxp_sk_your-secret'

The list envelope includes hasMore, count, and total at the top level. See Querying data for filter and pagination syntax.

Reference a student on a payment intent

{
  // ... useCase, deliveryMode, amountMode, etc.
  payer: {
    role: 'student',
    partyId: '6a20162451c558203a879c5f',  // student._id
  },
  subject: {
    role: 'student',
    partyId: '6a20162451c558203a879c5f',  // same student
  },
  recipients: [/* ... */],
}

If you don't set payer.details and provide only partyId, Core hydrates the personal details from the saved student at execution time. If you set both, the inline details win and the saved record is left unchanged.


Saved payers

Use POST /v2/payers when the payer is not a student — for example a parent paying on behalf of their child, an agent paying for many students, or a company funding tuition.

curl -X POST 'https://api.nexpay.com.au/v2/payers' \
  -H 'X-API-Key: nxp_ck_your-client-id:nxp_sk_your-secret' \
  -H 'Content-Type: application/json' \
  -d '{
    "payerType": "individual",
    "email": "jane.doe@example.com",
    "profile": {
      "firstName": "Jane",
      "lastName": "Doe",
      "phone": "+61412345678",
      "dob": "1972-09-30"
    },
    "address": {
      "country": "AU",
      "line1": "123 Main Street",
      "city": "Sydney",
      "state": "NSW",
      "postalCode": "2000"
    }
  }'

Reference on a payment intent the same way — payer.partyId: payer._id. Saved payers also hold identity documents via the same saved-document endpoints (see below).

See Creating a payer for the full field reference, including business payers (payerType: "business").


Saved-document reuse — the load-bearing optimisation

Without this, every payment for the same student requires re-uploading the same identity document. With it, you upload once and mint a fresh disposable copy for each payment.

The flow has four steps and involves three different ID fields that all look the same (UUIDs) but aren't interchangeable. Get the names right:

StepEndpointWhat ID it returnsWhere it goes next
  1. Upload the raw document
POST /v2/documentsdocumentId (response: { data: { documentId } })Sent as sourceDocumentId in step 2.
  1. Save against the student
POST /v2/students/{_id}/documentslegacyDocumentId (a new UUID; not the same as the source)Used as the path id in steps 3 and 4.
  1. List or look up the saved doc
GET /v2/students/{_id}/documentsdocuments[].legacyDocumentIdUsed as the path id in step 4.
  1. Mint a disposable copy for one payment
POST /v2/students/{_id}/documents/{legacyDocumentId}/usedocumentId (yet another new UUID — single-use)Pass this on the payment intent as instructions.manualPayment.payerIdentityDocumentId (or wherever an identity doc id is expected).

The disposable copy is consumed when the payment intent submits. Mint a fresh one for every new payment — they can't be reused across payments.

Worked example

# 1. Upload the passport once (first payment only)
curl -X POST 'https://api.nexpay.com.au/v2/documents' \
  -H 'X-API-Key: nxp_ck_your-client-id:nxp_sk_your-secret' \
  -F 'file=@passport.pdf'
# -> { "data": { "documentId": "30300c43-4012-436a-b422-2726f89cf7cd" } }

# 2. Save against the student (also first payment only)
curl -X POST 'https://api.nexpay.com.au/v2/students/6a20162451c558203a879c5f/documents' \
  -H 'X-API-Key: nxp_ck_your-client-id:nxp_sk_your-secret' \
  -H 'Content-Type: application/json' \
  -d '{
    "sourceDocumentId": "30300c43-4012-436a-b422-2726f89cf7cd",
    "type": "identity",
    "fileName": "passport.pdf",
    "contentType": "application/pdf"
  }'
# -> { "data": { "legacyDocumentId": "b4f958b9-0114-435c-a4aa-4d3e5df176b4" } }

Then, for every subsequent payment, skip the upload and just mint a fresh copy:

# 3 (next payment). List saved docs to find the identity one (optional)
curl 'https://api.nexpay.com.au/v2/students/6a20162451c558203a879c5f/documents' \
  -H 'X-API-Key: nxp_ck_your-client-id:nxp_sk_your-secret'
# -> find the entry where "type": "identity", read its legacyDocumentId

# 4. Mint a disposable copy for THIS payment only
curl -X POST 'https://api.nexpay.com.au/v2/students/6a20162451c558203a879c5f/documents/b4f958b9-0114-435c-a4aa-4d3e5df176b4/use' \
  -H 'X-API-Key: nxp_ck_your-client-id:nxp_sk_your-secret'
# -> { "data": { "documentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6" } }
# 5. Submit that disposable documentId as
#    instructions.manualPayment.payerIdentityDocumentId on the payment intent

What can be saved

The type field on the save endpoint accepts identity — identity documents (passport, driver's licence, etc.) — and is the most common case. Purpose-proof documents (enrolment letters, invoices) are not saved for reuse because they vary per payment.

The same endpoints exist on saved payers — POST /v2/payers/{_id}/documents, /use, etc. — with identical semantics.


Inline details — when you don't need persistence

For one-off flows where the payer never recurs, skip the POST /v2/students step entirely and pass payer.details inline:

{
  // ... useCase, etc.
  payer: {
    role: 'family',
    details: {
      payerType: 'parent',
      firstName: 'Jane',
      lastName: 'Doe',
      email: 'jane.doe@example.com',
      phone: '+61400000000',
      dob: '1972-09-30',
      addressLine1: '123 Main Street',
      city: 'Sydney',
      state: 'NSW',
      postcode: '2000',
      countryCode: 'AU',
    },
  },
  subject: {
    role: 'student',
    details: {
      firstName: 'Ada',
      lastName: 'Lovelace',
      email: 'ada@example.com',
    },
  },
  recipients: [/* ... */],
}

The fields on payer.details and subject.details are the same fields the POST /v2/students / POST /v2/payers endpoints accept. The intent stores them verbatim and never looks them up again.

For the identity document, you still need to upload it via POST /v2/documents and pass the resulting documentId to instructions.manualPayment.payerIdentityDocumentId. There is no reuse path without a saved party.


Things to know

  • A student's _id and a payer's _id are both Mongo ObjectIds (24 hex chars). Both are valid values for partyId on payment intents.
  • The partyId field doesn't tell Core which collection to look in — Core resolves the id against students and payers in turn.
  • Saved-document lists do not include the document content — they're metadata only. Use GET /v2/students/{_id}/documents/{legacyDocumentId}/content to download the original.
  • Disposable copies minted via /use expire if not submitted promptly. Mint right before you submit the intent.
  • Payment links (deliveryMode: reusable_payment_link) skip parties entirely on create — the payer's details and identity document are collected by the hosted page and recorded on the child payment intent.

Next steps

Previous
Quick start