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¶
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.
Response Shape¶
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 |