Overview
Employees belong to an Employer. They represent the individuals being paid — each with their own TFN, super fund, tax treatment, and STP Phase 2 classification.
Endpoints are nested under the employer:
GET /api/v1/employers/:employer_id/employees
POST /api/v1/employers/:employer_id/employees
GET /api/v1/employers/:employer_id/employees/:id
PATCH /api/v1/employers/:employer_id/employees/:id
The Employee object
Common fields (always returned)
| Field | Type | Notes |
|---|---|---|
id |
integer | |
employer_id |
integer | |
first_name |
string | |
last_name |
string | |
full_name |
string | Computed |
payroll_id |
string | Your system's ID for this employee. Must be unique within the employer. |
employment_basis |
string | F, P, C, L — see STP codes |
employment_basis_label |
string | Computed (e.g. "Full-time") |
income_type |
string | SAW, CHP, WHM, SWP, VOL, JPD |
income_type_label |
string | Computed (e.g. "Salary and wages") |
employment_start_date |
string (ISO 8601 date) | |
cessation_date |
string (ISO 8601 date, nullable) | When employment ended |
active |
boolean | |
terminated |
boolean | Computed. True if cessation_date is set and in the past |
created_at |
string (ISO 8601) | |
updated_at |
string (ISO 8601) |
Detail fields (only on GET /:id)
| Field | Type | Notes |
|---|---|---|
title |
string | Mr, Ms, Dr, etc. |
gender |
string | |
date_of_birth |
string (ISO 8601 date) | |
tfn_masked |
string | ***-***-782 — the last 3 digits only. Full TFN is never returned. |
email |
string | |
phone |
string | |
address_line_1 |
string | |
address_line_2 |
string | |
suburb |
string | |
state |
string | AU state code |
postcode |
string | |
cessation_reason |
string | Required when cessation_date is set |
income_type_country |
string | ISO 3166 country code, required for WHM income type |
tax_treatment_code |
string | See STP codes |
pay_rate_type |
integer | 0 = hourly, 1 = salaried |
pay_rate |
number | Decimal |
hours_per_pay_period |
number | Decimal |
super_fund_name |
string | |
super_usi |
string | Unique Superannuation Identifier |
super_member_number |
string | |
bank_account_name |
string | |
bank_bsb |
string | Formatted as 123-456 |
bank_account_number_masked |
string | Last 3 digits only |
Writeable fields
When creating or updating an employee, you can send any of these fields in the request body. TFN, super, bank, and address can all be updated independently.
{
"employee": {
"first_name": "Aria",
"last_name": "Patel",
"title": "Ms",
"gender": "F",
"date_of_birth": "1995-03-14",
"tfn": "123456782",
"email": "aria@acme.example",
"phone": "+61400000000",
"address_line_1": "12 Test St",
"suburb": "Sydney",
"state": "NSW",
"postcode": "2000",
"payroll_id": "EMP-001",
"employment_basis": "F",
"employment_start_date": "2024-07-01",
"income_type": "SAW",
"tax_treatment_code": "RTRR0000",
"pay_rate_type": 1,
"pay_rate": 120000.00,
"hours_per_pay_period": 76.00,
"super_fund_name": "Australian Retirement Trust",
"super_usi": "ATO0100AU",
"super_member_number": "12345678",
"bank_account_name": "A Patel",
"bank_bsb": "062-000",
"bank_account_number": "12345678"
}
}
TFN handling
- TFNs are encrypted at rest using Rails' built-in attribute encryption
- The full TFN is never returned by the API — only the masked form (last 3 digits)
- Pass a 9-digit TFN string with no spaces or dashes
- If you leave TFN blank, the ATO expects one of the substitution values (
000000000for no TFN quoted,111111111for applied for,333333333for under 18)
Endpoints
List employees for an employer
GET /api/v1/employers/:employer_id/employees
Scopes: employees:read
Query parameters:
| Param | Default | Notes |
|---|---|---|
include_terminated |
0 |
Set to 1 to include terminated employees |
page |
1 | |
per_page |
25 | Max 100 |
Response: 200 OK with an array of compact Employee objects.
curl https://stp.beeswaxapp.com/api/v1/employers/12/employees \
-H "Authorization: Bearer stp_test_..."
Get an employee
GET /api/v1/employers/:employer_id/employees/:id
Scopes: employees:read
Response: 200 OK with the full Employee object including detail fields.
Create an employee
POST /api/v1/employers/:employer_id/employees
Scopes: employees:write
Idempotent: yes
Body: see writeable fields above. first_name, last_name, and employment_basis are required. income_type defaults to SAW.
Response: 201 Created with full Employee object.
Update an employee
PATCH /api/v1/employers/:employer_id/employees/:id
Scopes: employees:write
Idempotent: yes
Body: any subset of the writeable fields.
Response: 200 OK with updated Employee object.
Terminating an employee
To mark an employee as terminated, set cessation_date and cessation_reason:
{
"employee": {
"cessation_date": "2026-03-31",
"cessation_reason": "V"
}
}
cessation_reason codes (STP Phase 2):
| Code | Meaning |
|---|---|
V |
Voluntary cessation |
I |
Ill health |
D |
Deceased |
R |
Redundancy |
F |
Dismissal |
C |
Contract cessation |
T |
Transfer |
O |
Other |
Terminated employees are excluded from GET /employees by default. Pass ?include_terminated=1 to see them. They still count against your free tier quota until you delete them (which you can only do via the web UI, for compliance reasons).
Validation rules
first_nameandlast_nameare requiredpayroll_idmust be unique within the employeremployment_basismust be one ofF,P,C,Lincome_typemust be one ofSAW,CHP,WHM,SWP,VOL,JPDstatemust be a valid Australian state code if providedpostcodemust be 4 digits if providedbank_bsbmust be 6 digits (with or without dash)
Common tasks
Bulk import employees from a CSV
while IFS=, read -r first last tfn payroll_id; do
curl https://stp.beeswaxapp.com/api/v1/employers/12/employees \
-X POST \
-H "Authorization: Bearer stp_live_..." \
-H "Idempotency-Key: employee-import-$payroll_id" \
-H "Content-Type: application/json" \
-d "{
\"employee\": {
\"first_name\": \"$first\",
\"last_name\": \"$last\",
\"tfn\": \"$tfn\",
\"payroll_id\": \"$payroll_id\",
\"employment_basis\": \"F\",
\"income_type\": \"SAW\",
\"employment_start_date\": \"2026-04-01\"
}
}"
done < employees.csv
The idempotency key keyed on payroll_id means you can rerun the import safely — existing employees won't be duplicated.