If you build anything that touches Australian businesses, sooner or later you need to know when one of them collapses. A customer with an unpaid invoice. A supplier you depend on. A tenant, a borrower, a franchisee.
ASIC publishes that information. Every winding up application, liquidator appointment, administration and creditors' meeting goes up on their Published Notices site within a day or so. It is public and free to read.
What does not exist is an ASIC public notices API. There is no official ASIC insolvencies API either, no JSON, no RSS, no bulk file. There is a search form and a CSV export button.
So I built the API. This post covers what is in it, how to call it, and where it falls short.
Why the official site is hard to use from code
Three things get in the way.
The search page is an old ASP.NET form. Paging, filters and the CSV export all post the entire page back to the server, including a 23 KB __VIEWSTATE blob. There is no URL you can construct to get page 4 of your filtered results.
The site sits behind AWS bot protection. Scripted requests to the search page get an empty HTTP 202 with an x-amzn-waf-action header. A browser gets through, a script does not.
Volume is misleading. About 80% of all notices are proposed deregistrations, posted in batches of two or three thousand at a time. If you want actual insolvency events, most of what you download is noise.
The way in is the sitemap. robots.txt points at a sitemap index, one file per month back to 2012, and each file lists every notice URL. Each notice page is plain HTML, and everything worth having is in the <head>: the company name, the ACN, the appointment type, the state, the notice code and the dates. So the collector reads the sitemap, fetches each new notice, stops reading at </head>, and stores the parsed row.
Right now that comes to about 312,000 notices covering the last 12 months, of which roughly 30,000 are real insolvency events rather than deregistrations.
What the data looks like
One notice, straight from the API:
{
"id": "6ce624e8-038a-4c93-acd1-06ed9be1974d",
"company_name": "BRIAGIN PTY LIMITED",
"acn": "163753428",
"other_names": null,
"notice_title": "NOTICE OF APPLICATION FOR WINDING UP ORDER",
"legal_reference": "Paragraph 465A(1)(c)",
"notice_code": "465A(1)(c)",
"appointment_type": "Winding Up Application",
"notice_purpose": "Winding up application",
"state": "NSW",
"company_status": "Registered",
"is_deregistration": false,
"published_date": "2026-09-17",
"appointment_date": "2026-08-13",
"source_url": "https://publishednotices.asic.gov.au/browsesearch-notices/notice-details/BRIAGIN-PTY-LIMITED-163753428/6ce624e8-038a-4c93-acd1-06ed9be1974d"
}
appointment_type is the field most people filter on. The values match ASIC's own dropdown: Court Liquidation, Creditors' Voluntary Liquidation, Members' Voluntary Liquidation, Voluntary Administration, Restructuring (Part 5.3B), Deed of Company Arrangement, Winding Up Application, Scheme of Arrangement, Deregistration.
source_url always points back to the original notice, so anything you show a user can be checked against ASIC.
Search
Authentication is one header.
curl "https://api.insolvencyalerts.com.au/v1/notices?q=briagin" \
-H "X-API-Key: YOUR_API_KEY"
q searches company names, including former names and registered business names, and partial words work. Pass a 9-digit number and it is treated as an ACN.
The filters stack:
?q=drifta name search
?acn=643233676 exact company
?appointment_type=Court Liquidation,Voluntary Administration
?notice_code=465A(1)(c) Corporations Act section
?state=NSW,VIC
?from=2026-09-01&to=2026-09-30 published date
?include_deregistration=true off by default
?sort=published_asc&limit=50&page=2 max limit is 100
Deregistration notices are hidden unless you ask for them, because otherwise they drown everything else. The exception is an ACN search, where you probably want the company's full history.
GET /v1/filters returns every filter value in the database with counts, so you can build dropdowns without hardcoding my list. GET /v1/stats?group_by=month gives grouped counts if you want to chart insolvencies over time.
ABN lookup
Notices only carry an ACN. Most business systems store an ABN.
So the API keeps a copy of ASIC's Company Dataset from data.gov.au, refreshed weekly, currently about 4.4 million rows. Pass either identifier and it resolves:
curl "https://api.insolvencyalerts.com.au/v1/companies/32613554233" \
-H "X-API-Key: YOUR_API_KEY"
Worth knowing if you are building this yourself: an ABN is not an ACN with a prefix. It often looks that way, but trusts, sole traders and partnerships hold an ABN and no ACN at all, and foreign companies have an ARBN in the same 9-digit shape as an ACN. Resolution has to be a lookup, never arithmetic.
Screening a list
The common job is not one company, it is a whole ledger. POST /v1/match takes up to 50,000 identifiers, mixed ACNs and ABNs, and tells you which ones have notices. It stores nothing.
{
"data": {
"checked": 2,
"matched": 1,
"matches": [{ "acn": "163753428", "notice_count": 3 }],
"unresolved": []
}
}
Anything unresolvable comes back in unresolved rather than being quietly dropped, which matters because a fair share of notices are for companies the register does not cover.
Polling without missing anything
Every notice gets a seq, assigned once when it is first stored and never changed. Poll with it:
curl "https://api.insolvencyalerts.com.au/v1/notices?since=4821" \
-H "X-API-Key: YOUR_API_KEY"
# { "data": [ ... ], "meta": { "next_since": 4877 } }
Keep the next_since and send it back next time. No repeats, no gaps.
A timestamp cursor does not work here, and this took me a while to see. Notices arrive out of order. A notice published in March can be collected today, during backfill or after a retry. Filter on published_date and you miss it. Filter on a "last updated" timestamp and you resend everything you re-fetched. A monotonic sequence assigned at insert is the only thing that gives both guarantees.
Or skip polling
Create a watch over a list of companies and get a POST when one of them appears in a notice.
POST /v1/watches
{
"name": "debtor book",
"identifiers": ["163753428", "32613554233"],
"appointment_type": ["Court Liquidation"],
"include_deregistration": false
}
Attach an endpoint with POST /v1/watches/{id}/webhook and deliveries arrive signed:
POST https://your-app.example/asic
X-ASIC-Signature: sha256=<hex of HMAC-SHA256 over the raw body>
X-ASIC-Delivery: dlv_...
{
"watch_id": "wch_...",
"delivered_at": "2026-09-23T01:15:00.000Z",
"notice": { "company_name": "BRIAGIN PTY LIMITED", "acn": "163753428" }
}
Recompute the HMAC over the raw body and compare. X-ASIC-Delivery is stable across retries, so use it to deduplicate. Failures retry with backoff and GET /v1/watches/{id}/deliveries shows you the status, the attempt count and the last error your endpoint returned, which is usually enough to work out what broke without asking me.
Every endpoint
| Method | Path |
|---|---|
| GET | /v1/notices |
| GET | /v1/notices/{id} |
| GET | /v1/companies/{acn_or_abn} |
| GET | /v1/filters |
| GET | /v1/stats |
| POST | /v1/match |
| GET POST | /v1/watches |
| GET PATCH DELETE | /v1/watches/{id} |
| POST DELETE | /v1/watches/{id}/acns |
| GET | /v1/watches/{id}/matches |
| POST DELETE | /v1/watches/{id}/webhook |
| GET | /v1/watches/{id}/deliveries |
| GET | /health |
Errors are a code and a plain message: unauthorised, subscription_inactive, quota_exceeded, watch_limit_reached, account_required, not_found, method_not_allowed. Quota is checked before anything is written, so a request that would take you past your plan limit changes nothing.
The honest caveats
ASIC's sitemap runs about a day behind, so expect a notice within a day of publication, not within minutes.
History is the last 365 days, with older years being backfilled.
The company register is a weekly snapshot. ASIC Connect is the authoritative source for a company's current status.
A notice means a notice was published. It is not a credit rating, and it is not legal advice.
And this is not an ASIC service. It reads their public notices and links back to every one. Not affiliated with or endorsed by ASIC.
Try it
GET /health needs no key and shows the oldest and newest notice held, if you just want to see it respond.
Docs are at insolvencyalerts.com.au/docs and there is a 7 day free trial at insolvencyalerts.com.au/pricing.
If you have built something against ASIC data and solved a piece of this differently, I would like to hear it. The sitemap trick took me longer to find than it should have.
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.