What you'll do

This walkthrough takes you from a brand-new Beeswax STP account to your first accepted ATO pay event in the EVTE sandbox environment. Takes under 10 minutes, all via curl. You'll create an employer, add an employee, build a pay event, and lodge it.

Prerequisites

  • A Beeswax STP account on the API plansign up free and upgrade from Billing & Plan
  • A test token created from Settings → API Tokens (prefix: stp_test_...)
  • curl or any HTTP client

In every example below, replace stp_test_... with your actual token.

Shortcut: spin up a sandbox with one call

If you just want to poke at the API, skip straight to:

curl -X POST https://stp.beeswaxapp.com/api/v1/sandbox/seed \
  -H "Authorization: Bearer stp_test_..."

This returns a ready-made test employer with three employees — full details in Sandbox seed. If you'd rather do it by hand, carry on with Step 1 below.

Step 1 — Create an employer

Employers represent the business entity lodging pay events. You need at least one per ABN.

curl https://stp.beeswaxapp.com/api/v1/employers \
  -X POST \
  -H "Authorization: Bearer stp_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "employer": {
      "legal_name": "Acme Pty Ltd",
      "trading_name": "Acme",
      "abn": "51824753556",
      "branch_number": 1,
      "bms_id": "acme-001",
      "contact_name": "Finance",
      "contact_email": "finance@acme.example",
      "environment": "evte"
    }
  }'

Sample response (HTTP 201 Created):

{
  "id": 12,
  "legal_name": "Acme Pty Ltd",
  "trading_name": "Acme",
  "display_name": "Acme",
  "abn": "51824753556",
  "formatted_abn": "51 824 753 556",
  "branch_number": 1,
  "environment": "evte",
  "active": true,
  "stp_configured": false,
  "employee_count": 0,
  "bms_id": "acme-001",
  "contact_name": "Finance",
  "contact_email": "finance@acme.example",
  "created_at": "2026-04-09T11:32:05Z",
  "updated_at": "2026-04-09T11:32:05Z"
}

Note the id: 12 — you'll use it in the next step.

Why environment: "evte"? Test tokens only see EVTE employers. If you try to create a production employer with a test token, it'll be invisible. See Environments.

Step 2 — Add an employee

Employees live under an employer.

curl https://stp.beeswaxapp.com/api/v1/employers/12/employees \
  -X POST \
  -H "Authorization: Bearer stp_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "employee": {
      "first_name": "Aria",
      "last_name": "Patel",
      "tfn": "123456782",
      "date_of_birth": "1995-03-14",
      "employment_start_date": "2024-07-01",
      "employment_basis": "F",
      "income_type": "SAW",
      "tax_treatment_code": "RTRR0000",
      "payroll_id": "EMP-001"
    }
  }'

Sample response (HTTP 201):

{
  "id": 88,
  "employer_id": 12,
  "first_name": "Aria",
  "last_name": "Patel",
  "full_name": "Aria Patel",
  "payroll_id": "EMP-001",
  "employment_basis": "F",
  "employment_basis_label": "Full-time",
  "income_type": "SAW",
  "income_type_label": "Salary and wages",
  "employment_start_date": "2024-07-01",
  "active": true,
  "terminated": false,
  "tfn_masked": "***-***-782"
}

TFNs are encrypted at rest and only ever returned masked. Never logged in plaintext anywhere.

See the STP Phase 2 code reference for employment_basis, income_type, and tax_treatment_code values.

Step 3 — Create a pay event

A pay event represents one pay run — the container for all the individual employee pay items.

curl https://stp.beeswaxapp.com/api/v1/pay_events \
  -X POST \
  -H "Authorization: Bearer stp_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "pay_event": {
      "employer_id": 12,
      "pay_period_start": "2026-04-01",
      "pay_period_end": "2026-04-14",
      "payment_date": "2026-04-14",
      "pay_frequency": "fortnightly",
      "event_type": "pay_event"
    }
  }'

Sample response (HTTP 201):

{
  "id": 300,
  "employer_id": 12,
  "employer_name": "Acme",
  "pay_period_start": "2026-04-01",
  "pay_period_end": "2026-04-14",
  "period_label": "1 Apr – 14 Apr 2026",
  "payment_date": "2026-04-14",
  "pay_frequency": "fortnightly",
  "event_type": "pay_event",
  "status": "draft",
  "employee_count": 0,
  "total_gross": 0.0,
  "total_tax": 0.0,
  "total_super": 0.0
}

The pay event starts in draft status. We'll add items, then mark it ready, then submit.

Step 4 — Add a pay event item

Each item represents one employee's pay for this period, with disaggregated STP Phase 2 fields.

curl https://stp.beeswaxapp.com/api/v1/pay_events/300/items \
  -X POST \
  -H "Authorization: Bearer stp_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "item": {
      "employee_id": 88,
      "hours_paid": 76.0,
      "gross_payment": 4820.00,
      "ordinary_time_earnings": 4820.00,
      "payg_withholding": 1145.00,
      "super_guarantee": 554.30
    }
  }'

All monetary fields are decimal numbers in AUD. Hours are decimal. Fields you don't include default to 0.00.

Step 5 — Mark ready and submit

# Mark the pay event ready for ATO submission
curl https://stp.beeswaxapp.com/api/v1/pay_events/300/mark_ready \
  -X POST \
  -H "Authorization: Bearer stp_test_..."

# Submit to the ATO (EVTE, since we used a test token)
curl https://stp.beeswaxapp.com/api/v1/pay_events/300/submit \
  -X POST \
  -H "Authorization: Bearer stp_test_..."

The submit endpoint returns immediately with the pay event now in submitted status. The actual lodgement happens asynchronously in a background job. To know when the ATO has accepted or rejected the submission, you have two options:

  1. Poll GET /api/v1/submissions — look for the submission status changing from pending / sentaccepted / rejected
  2. Configure a webhook so we call your server when the status changes. This is strongly recommended for production. See Webhooks.

Step 6 — Check the submission status

curl "https://stp.beeswaxapp.com/api/v1/submissions?employer_id=12" \
  -H "Authorization: Bearer stp_test_..."
[
  {
    "id": 501,
    "pay_event_id": 300,
    "employer_id": 12,
    "employer_name": "Acme",
    "status": "accepted",
    "environment": "evte",
    "event_type": "pay_event",
    "sent_at": "2026-04-09T11:33:41Z",
    "response_received_at": "2026-04-09T11:33:58Z",
    "created_at": "2026-04-09T11:33:40Z"
  }
]

You're done. In production the same flow works — just use a stp_live_... token, a production environment employer, and the ATO receives the real submission.

Next steps