> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs-unsw-v6.advance-uac.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-unsw-v6.advance-uac.com/_mcp/server.

# Correcting records

Applicants change their name. Application numbers get re-keyed. A stream is captured wrong and
noticed a week later. Two endpoints exist for putting those right:

```
PATCH /institution/applications/{id}
PATCH /institution/applicants/{id}
```

Both follow [JSON Merge Patch](https://datatracker.ietf.org/doc/html/rfc7386): send only what
you want to change.

| In your body                | What happens                 |
| --------------------------- | ---------------------------- |
| A field with a value        | It is set.                   |
| A field with `null`         | It is cleared.               |
| A field you leave out       | It is left alone.            |
| A field name we do not know | **400.** Nothing is written. |

That last row is deliberate. Under merge semantics an ignored typo does nothing at all and
looks exactly like success, so `{"programme": "3778"}` is rejected rather than quietly
accepted:

```json
{
  "status": 400,
  "error": "Unknown field(s) [programme] — patchable fields are [description, intakeCode, programCode, sourceName, sourceRef, sources, stream, year]"
}
```

## Correcting an application

`sources`, `sourceName`, `sourceRef`, `programCode`, `year`, `stream`, `intakeCode` and
`description`.

`programCode` and `year` name a programme *together*, so sending one keeps the other. To move
an application to the same programme code in a different commencement year, send only the year:

```json
{ "year": 2027 }
```

### The intake

`intakeCode` is your own code for the term the applicant is starting — `"5269"` for Term 3
2026\. These are your term codes, loaded from the intake schedule you supply us, so a code you
use is a code we hold. One we do not recognise is a `400` naming it:

```json
{
  "status": 400,
  "error": "No intake with code 9999"
}
```

Send `null` to clear it. It is optional, but our officers work applications in intake order,
so one with no intake cannot be prioritised against the rest.

> **Note**
>
> **The intake is not the commencement year.** `year` picks the programme and the credit rules
> the application is assessed against; `intakeCode` says which term the applicant actually
> starts. The two can legitimately disagree — an application sent in 2026 for Summer Term 2027
> has `year: 2026` and an intake beginning 4 January 2027 — and neither is derived from the
> other.

### What an assessment freezes

Once an application has been assessed, `programCode`, `year` and `stream` can no longer be
changed:

```json
{
  "status": 409,
  "error": "[stream] cannot be changed once the application has been assessed — the credit already granted was worked out against the programme and stream it had then. Submit a new application instead."
}
```

**`intakeCode` is not frozen,** and that is the point of it being separate from `year`. Nothing
is assessed against the intake, so correcting it on an assessed application leaves the credit
already granted true.

The credit on that application was worked out against the programme it had at the time, and
nothing in this API can work it out again. Accepting the change would leave a record quietly
disagreeing with itself — credit for one programme, filed under another.

`sources`, `sourceName`, `sourceRef` and `description` stay correctable at any point, because
none of them affects what the credit was assessed against.

> **Note**
>
> If the programme really is wrong on an assessed application, submit a new one. It will be
> assessed against the right programme from the start.

## Correcting an applicant

`givenName1`, `givenName2`, `familyName`, `dob`, `emailAddress`, `phoneNumber`,
`postalAddress`, `sources`, `sourceName` and `sourceRef`.

A person cannot exist without `givenName1`, `familyName`, `dob` and `emailAddress`, so those
four can be **changed but not cleared**. Sending one as `null` is a 400. The rest can be
cleared freely:

```json
{
  "familyName": "Nguyen-Barrett",
  "emailAddress": "t.nguyen@student.example.edu.au",
  "phoneNumber": null
}
```

This is exactly why recording your own references on an applicant is worth it. Names and email
addresses move; your student number does not, and it goes on finding the person afterwards.

## Correcting the references

An applicant or an application can hold one reference per system of record. There are two ways
to correct them, and they do different things.

**`sources` replaces the whole set.** Send it in the order you want, first entry primary:

```json
{
  "sources": [
    { "sourceName": "SITS", "sourceRef": "z1234567" },
    { "sourceName": "TRIM", "sourceRef": "T-99814" }
  ]
}
```

Because it replaces, an entry you leave out is removed. Sending `"sources": []` clears them
all. Omitting the field entirely leaves every reference alone — that is the difference between
an empty array and an absent one.

**The `sourceName` / `sourceRef` pair edits the first entry**, leaving the others as they are.
This is the older form and it still works exactly as it did:

```json
{ "sourceRef": "z7654321" }
```

On a record holding `[SITS/z1234567, TRIM/T-99814]`, that leaves `[SITS/z7654321,
TRIM/T-99814]` — the system is kept, the id corrected, and the TRIM entry untouched.

## Re-using a `sourceRef`

A `sourceRef` is unique within a `sourceName`, across every reference we hold rather than
just the primary ones. Moving one onto a pair another record already holds is refused, and the
error names the record holding it so you can go and look:

```json
{
  "status": 409,
  "error": "sourceRef APP-2026-00417 (SITS) already belongs to application 4d8f0098-b3ef-4a6c-b797-4499da03c81e"
}
```

Clearing `sourceName` while a `sourceRef` remains is also refused: an id with no system to
interpret it cannot be looked up. Clear both together, or neither.

## Why there is no PUT here

The catalogue endpoints offer both `PUT` and `PATCH`. Applications and applicants offer only
`PATCH`, on purpose.

`PUT` replaces, so every field you omit is cleared — and for a feed sending partial records
that failure is silent. A system that knows only its own reference and the stream would wipe
the description and the source pair on every send, and nothing would report an error. `PATCH`
expresses everything `PUT` would without that risk, including clearing a field, which you do
explicitly with `null`.

## What you cannot patch

Qualifications. They have their own endpoint and their own validation:

```
POST /institution/applications/{id}/qualifications
```

Sending `qualifications` in a patch body is a 400, like any other unknown field.