# Structure and encoding

Every data file has the same two top-level properties, whichever interface code you use.

| Field | Type | Required | Notes |
|  --- | --- | --- | --- |
| `InterfaceCode` | string | Yes | Must match the `InterfaceCode` in the request envelope. |
| `TransformedItems` | array | Yes | Between 1 and 5,000 items. The shape of each item depends on the interface code. |


An empty array returns `STAGING_EMPTY_BATCH`. More than 5,000 items returns `STAGING_BATCH_LIMIT_EXCEEDED`.

Each item needs a `SourceTransactionId` that is unique within the file. It is used for validation only and is not stored, so it cannot be used afterwards to match a transaction to its outcome — the processed-items response identifies transactions by their 1-based position in `TransformedItems`.

## Transaction dates

Every transaction must be dated in a financial year the fund has open. A transaction dated in a period the fund has closed is discarded: it does not load, and it is not reported as failed or warned. The file can still report `Successful`, with that transaction simply missing from the counts.

Check the dates in your file against the fund's open period before you submit.

## Identifying a holding account

Every item names the holding account its transaction belongs to. There are several ways to do
that — a holding `Code`, a `BankAccount` with BSB and account number, an `InvestmentAccount` with
a security code, a `TermDepositAccount`.

**`Code` works for cash, portfolio, income and term deposit.** Every holding in Class has a code, visible on the Browse
Holding Accounts screen, and naming it directly is the simplest and least ambiguous option. The
others exist so you can match on identifiers your own system already holds — a BSB and account
number from a bank feed, a security code from a broker file — without maintaining a mapping to
Class's codes.

**Every identifier you supply takes part in the lookup.** They are not metadata carried through to
the transaction. `ExternalId` carries the Fund Holding Reference (FHR) account number, such as a broker account number, `ClientID` a term deposit
account number or HIN/SRN, and `HIN` or `SRN` a holder number — each is used to find the holding,
and a value that does not match what Class holds fails the transaction with
`REFERENCE_LOCATOR_FUND_NOT_FOUND`, even when everything else on the transaction is correct.

Supply the smallest set that identifies the account, and add more only to disambiguate — for
example when a fund holds the same security through two brokers.

## Property names

Use PascalCase, as shown throughout this documentation. Responses use PascalCase too.

Unknown properties are ignored rather than rejected, on both the envelope and the data file. A misspelled property name produces no error and its value never arrives, so check names against the schemas rather than relying on validation to catch them.

Property order is irrelevant.

## Encoding

Encode the document as UTF-8, then Base64 (RFC 4648). No line breaks, no data URI prefix.

**Python**

```python
import json, base64
payload = base64.b64encode(json.dumps(document).encode("utf-8")).decode()
```

**Node**

```javascript
const payload = Buffer.from(JSON.stringify(document)).toString("base64");
```

**C#**

```csharp
var payload = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
```

Content that is not valid Base64, or that does not decode to a valid JSON document, returns `STAGING_INVALID_INNER_PAYLOAD`.