Skip to content

TEQSA API Reference

Location: docs/docs/ops/teqsa-api-reference.md

Worker: rtopacks-teqsa-sync

Last updated: 2026-04-10 (Session 48)


Overview

TEQSA (Tertiary Education Quality and Standards Agency) publishes its provider, course, and regulatory decision data via the Australian Government's data.gov.au CKAN datastore API. This is a public, unauthenticated API.

The teqsa-sync worker polls this API monthly (cron: 0 5 1 * *) and on manual trigger from the Observatory. Data is stored in rto-licensing-db (LICENSING_DB).


Base URL

https://data.gov.au/data/api/3/action/datastore_search

No authentication required. No API key. Public access.


Resource IDs

Resource ID Records (approx)
Providers 07370e3f-780b-4a70-8c87-b6796d5ab237 269
Courses 9277422c-0281-46c2-8d0d-a7c43d712108 2,894
Decisions a61abca4-a4b7-4f17-a975-0bba20c2c73f 5,982

Pagination

Offset-based. 100 records per page is the recommended page size.

GET /datastore_search?resource_id={ID}&limit=100&offset=0
GET /datastore_search?resource_id={ID}&limit=100&offset=100
...

Stop condition: result.records.length < 100 (last page).

Important: data.gov.au is slow. Response times of 10–25 seconds per page are observed under normal conditions. Always set a fetch timeout of 25 seconds minimum. Without a timeout, the Worker will hang and be killed by the CF CPU limit with no error row written. See ops/source-of-truth-connectivity.md for the full cross-endpoint gotcha matrix.

fetch(url, { signal: AbortSignal.timeout(25000) })

Response Shape

{
  "result": {
    "records": [ ... ],
    "total": 269,
    "offset": 0,
    "limit": 100
  },
  "success": true
}

Field Reference

Providers (teqsa_providers)

API Field DB Column Notes
ProviderID provider_id PK. Format: PRV12002
ProviderName provider_name
ProviderTradingName provider_trading_name nullable
ABN abn nullable
Category category Australian University, NZ University,
Self-Accrediting HE, etc.
Address address nullable
Website website nullable
RegistrationStatus registration_status Active / Inactive
RegistrationDescription registration_description nullable
RegistrationRenewalDate registration_renewal_date nullable, date string DD/MM/YYYY
Years registration_years e.g. "7 years - maximum allowable period"
SelfAccreditation self_accreditation Yes / No
CRICOS Registration cricos_code nullable, CRICOS provider code
CRICOS Web cricos_url nullable
ASQALink asqa_url nullable — present on dual-regulated only
(derived) asqa_rto_code extracted from ASQALink URL
QILT qilt_url nullable
(derived) is_dual_regulated 1 if ASQALink present, else 0

Note on self-accrediting universities: Providers with SelfAccreditation = Yes (e.g. Group of Eight universities — ANU, UNSW, Melbourne, etc.) accredit their own courses internally. Their courses do NOT appear in the courses resource. Only non-self-accrediting providers have course records in the API.

Dual-regulated providers: ~71 providers have both a TEQSA registration and an ASQA RTO number (asqa_rto_code). These are primarily TAFEs and some private providers. The is_dual_regulated flag enables cross-registry joins.

Courses (teqsa_courses)

API Field DB Column Notes
CourseID course_id PK. Format: CRS1200011
ProviderID provider_id FK → teqsa_providers.provider_id
CourseName course_name Full course title
Accreditation accreditation Active / Inactive
AccreditationDate accreditation_date Date string DD/MM/YYYY
AccreditationStatusDate accreditation_status_date Date string DD/MM/YYYY
AccreditationStatus accreditation_status Active / Expired / Withdrawn
Years years Accreditation period or "Not Applicable"
LOTE lote Language Other Than English — Yes / No

Decisions (teqsa_decisions)

API Field DB Column Notes
ID id PK. Format: ID0001
ProviderID provider_id FK → teqsa_providers.provider_id
CourseID course_id nullable — FK → teqsa_courses.course_id
DecisionType decision_type Accreditation / Registration / etc.
DecisionDate decision_date nullable, date string
Title title Human-readable decision description

Worker Architecture

The teqsa-sync worker uses a chained step architecture. Each step gets its own 30-second CF Worker CPU budget. Steps chain via direct HTTP POST (not ctx.waitUntil).

/trigger or scheduled()
  → POST /run {step: "providers"}
    → fetchAll(providers) + db.batch() upsert
    → POST /run {step: "courses"}
      → fetchAll(courses) + db.batch() upsert
      → POST /run {step: "decisions"}
        → fetchAll(decisions) + db.batch() upsert
        → POST /run {step: "finalize"}
          → write sync log + snapshot to OPS_DB

D1 writes use db.batch() in chunks of 100 to avoid per-row await overhead.

Standing rule (OBS-INTEGRITY-02): Never use ctx.waitUntil(fetch(...)) for chaining in /run handlers. The fetch must be awaited before the response is returned, or use ctx.waitUntil(chainNext(...)) only in scheduled() handlers where no response is expected.


DB Location

All TEQSA data stored in rto-licensing-db (LICENSING_DB). DB ID: 400fd979-b5f9-460e-b4e2-3af074ecec31

Tables: teqsa_providers, teqsa_courses, teqsa_decisions

Sync steps logged in rto-ops-db (OPS_DB) → tga_sync_steps with sync_type = 'teqsa_sync'.


Verified Record Counts (2026-04-10)

Table Count
teqsa_providers 269
teqsa_courses 2,894
teqsa_decisions 5,982