Sandbox and test keys
Develop against ASIC sample data for free with asicapi test keys, learn how placeholder names and images behave, and simulate errors with valid test ACNs.
The asicapi sandbox lets you build and test an ASIC integration without paying statutory fees. Requests made with an asicapi_test_ key run against ASIC's sample client, a special account ASIC gives information brokers for testing and demonstrations. The register structure, codes, dates and document lists are real, but names of commercial value are replaced with placeholders, no fees are levied, and document images are only served for ASIC's public sample company 009 136 109. Everything else, from the URL paths to the error codes, is identical to production.
Using the sandbox
Create a test key in the dashboard and use it exactly like a live key against the same base URL. The sandbox follows the same three tiers as production (see free lookups, extracts and orders): free lookups are free, a purchase returns 201 with a real extract id, and an order returns 202. The only difference is that meta.billable is always false. Purchase a company extract first, then read it.
curl -X POST https://api.asicapi.dev/v1/companies/009136109/extracts \
-H "Authorization: Bearer asicapi_test_5Kx2mQ9pL7vN3rT8wY1zB4cD6fG0hJ" \
-H "Content-Type: application/json" \
-d '{ "type": "current" }'{
"object": "extract",
"id": "ext_01J9ABTEST0001",
"kind": "company",
"type": "current",
"subject": {
"acn": "009136109",
"formatted": "009 136 109",
"numberType": { "code": "ACN", "label": "Australian Company Number" },
"name": "ASIC SAMPLE COMPANY PTY LTD",
"type": { "code": "APTY", "label": "Australian Proprietary Company" },
"status": { "code": "REGD", "label": "Registered" },
"abn": null,
"registeredCharity": false
},
"purchasedAt": "2026-09-04T03:12:44Z",
"asOf": "2026-09-04T03:12:41Z",
"expiresAt": "2027-09-04T03:12:44Z",
"officeholders": [
{
"object": "officeholder",
"role": { "code": "DR", "label": "Director" },
"status": { "code": "C", "label": "Current" },
"appointedAt": "2012-06-18",
"ceasedAt": null,
"party": {
"type": "person",
"person": { "familyName": "FAMILY NAME", "givenNames": ["GIVEN NAME1", "GIVEN NAME2"], "formatted": "GIVEN NAME1 GIVEN NAME2 FAMILY NAME" },
"birth": { "date": "1970-01-01", "locality": "LOCALITY", "stateOrCountry": "NSW" },
"organisation": null
},
"address": { "careOf": null, "line1": null, "street": "1 SAMPLE STREET", "locality": "SYDNEY", "state": "NSW", "postcode": "2000", "country": "AUSTRALIA" },
"sourceDocument": { "documentNumber": "0E5123456", "qualifier": null },
"cessationDocuments": [],
"court": null
}
],
"meta": { "billable": false, "product": null, "requestId": "req_01J8ZKJ7J2K6L0" }
}The extract is stored and readable for 12 months like a live one, so the section endpoints now work for this company.
curl https://api.asicapi.dev/v1/companies/009136109/officeholders \
-H "Authorization: Bearer asicapi_test_5Kx2mQ9pL7vN3rT8wY1zB4cD6fG0hJ"{
"object": "list",
"data": [
{
"object": "officeholder",
"role": { "code": "DR", "label": "Director" },
"status": { "code": "C", "label": "Current" },
"appointedAt": "2012-06-18",
"ceasedAt": null,
"party": {
"type": "person",
"person": { "familyName": "FAMILY NAME", "givenNames": ["GIVEN NAME1", "GIVEN NAME2"], "formatted": "GIVEN NAME1 GIVEN NAME2 FAMILY NAME" },
"birth": { "date": "1970-01-01", "locality": "LOCALITY", "stateOrCountry": "NSW" },
"organisation": null
},
"address": {
"careOf": null,
"line1": null,
"street": "1 SAMPLE STREET",
"locality": "SYDNEY",
"state": "NSW",
"postcode": "2000",
"country": "AUSTRALIA"
},
"sourceDocument": { "documentNumber": "0E5123456", "qualifier": null },
"cessationDocuments": [],
"court": null
}
],
"hasMore": false,
"nextCursor": null,
"totalCount": null,
"extract": { "id": "ext_01J9ABTEST0001", "type": "current", "purchasedAt": "2026-09-04T03:12:44Z", "asOf": "2026-09-04T03:12:41Z" },
"meta": { "billable": false, "product": null, "requestId": "req_01J8ZKJ8K3L7M1" }
}Skip the purchase and the section endpoint returns 402 extract_required exactly as it would in production, which makes the sandbox the right place to test your buy-then-read handling.
How sample data differs from live data
| Aspect | Sandbox behaviour |
|---|---|
| Names | Office holder, member and related party names are replaced with placeholders such as FAMILY NAME, GIVEN NAME1. Company names are returned as held |
| Fees | Never charged. Every response has "meta": { "billable": false, "product": null }, including the 201 from a purchase and the 202 from an order |
| Extracts | Purchases succeed and return a real ext_ id. The extract is stored for 12 months and readable through GET /v1/extracts/{id} and the section endpoints, with placeholder names |
| Document images | Available only for documents belonging to company 009 136 109. Image orders for any other document return document_not_imaged |
| Charges extract orders | Available only for company 009 136 109 |
| Weekly summaries | Not served by ASIC's sample client. Every /v1/weekly-summaries/{type} request returns 403 sandbox_product_unavailable |
| People search | Works, with placeholder names in results and extracts |
| Registers | Browse and extract work with placeholder names |
| Offline searches | Accepted and delivered, with placeholder data |
| Webhooks | Delivered normally to endpoints configured for the test environment |
| Rate limits | Same as live: 600 requests per minute, 20 concurrent |
Because names are placeholders, write your tests against structure (field presence, codes, dates, counts) rather than against specific name strings. Codes and labels are real, so role.code === 'DR' is a stable assertion; party.person.familyName === 'SMITH' is not.
Sample data is still ASIC data
The sandbox reads ASIC's register with names masked, so registration dates, statuses and document lists reflect the real records for the ACNs you query. Do not assume a company in the sandbox is fictional.
Test ACNs
ASIC publishes these numbers as valid ACNs for check digit testing. Each passes the mod 10 weighted check and is accepted by every endpoint; whether ASIC holds a record behind it varies, which makes the set useful for exercising both the success and the company_not_found path.
| 000 000 019 | 000 250 000 | 000 500 005 | 000 750 005 |
| 001 000 004 | 001 250 004 | 001 500 009 | 001 749 999 |
| 001 999 999 | 002 249 998 | 002 499 998 | 002 749 993 |
| 002 999 993 | 003 249 992 | 003 499 992 | 003 749 988 |
| 003 999 988 | 004 249 987 | 004 499 987 | 004 749 982 |
| 004 999 982 | 005 249 981 | 005 499 981 | 005 749 986 |
| 005 999 977 | 006 249 976 | 006 499 976 | 006 749 980 |
| 006 999 980 | 007 249 989 | 007 499 989 | 007 749 975 |
| 007 999 975 | 008 249 974 | 008 499 974 | 008 749 979 |
| 008 999 979 | 009 249 969 | 009 499 969 | 009 749 964 |
| 009 999 964 | 010 249 966 | 010 499 966 | 010 749 961 |
Two more numbers are worth knowing:
- 009 136 109 is ASIC's public sample company. Its document list, document images and charges extract all work in the sandbox, so use it for any end-to-end test that needs a PDF.
- 004 085 616 is the worked example in ASIC's check digit algorithm and is used throughout these docs.
The check digit algorithm: weight the first eight digits 8, 7, 6, 5, 4, 3, 2, 1, sum the products, take the remainder mod 10, and subtract it from 10 (a result of 10 becomes 0). For 004 085 616 the products sum to 84, the remainder is 4, and 10 minus 4 gives the check digit 6. ARBNs use the same formula. GET /v1/identifiers/{value} runs this for you.
Simulating errors
Most errors can be triggered with ordinary requests. For conditions that depend on ASIC's state, the sandbox accepts an X-Sandbox-Simulate header naming the error code to return.
| Error to reproduce | How |
|---|---|
acn_invalid | Request /v1/companies/004085617 (last digit changed) |
company_not_found | Request a test ACN ASIC holds no record for, for example /v1/companies/001749999 |
abn_invalid | Request /v1/companies/53004085617 |
abn_not_acn_based | Request an 11-digit ABN whose last nine digits fail the ACN check |
no_matches | Search q=ZZZZQQQQ%20PTY%20LTD&exact=true |
too_many_matches | Search q=PTY with scope=everything-current-and-deregistered |
name_invalid_characters | People search with familyName=SMITH. |
extract_required | Call /v1/companies/{id}/officeholders for a company you have not purchased an extract for, or request status=all while holding only a current extract |
extract_expired | X-Sandbox-Simulate: extract_expired on GET /v1/extracts/{id} or a section endpoint |
extract_unavailable_for_type | Purchase an extract for an ASIC identifier that belongs to a business name |
search_expired | Use a person id from a search made more than 30 days ago, or send X-Sandbox-Simulate: search_expired |
document_not_imaged | Order an image for any document not belonging to 009 136 109 |
page_range_invalid | Order pages 1 to 99 of a four-page document |
document_too_large_for_delivery | Order with delivery.method=email and send X-Sandbox-Simulate: document_too_large_for_delivery |
sandbox_product_unavailable | Request any weekly summary |
product_not_enabled | Search with jurisdiction=QLD on an account without Queensland enabled |
product_unavailable_in_jurisdiction | Search with jurisdiction=VIC (Victoria) |
rate_limited | Send more than 600 requests in a minute, or X-Sandbox-Simulate: rate_limited |
asic_unavailable | X-Sandbox-Simulate: asic_unavailable |
asic_application_error | X-Sandbox-Simulate: asic_application_error |
order.failed webhook | Create an image order with X-Sandbox-Simulate: order_failed; the order moves to failed after a few seconds |
curl https://api.asicapi.dev/v1/companies/004085616 \
-H "Authorization: Bearer asicapi_test_5Kx2mQ9pL7vN3rT8wY1zB4cD6fG0hJ" \
-H "X-Sandbox-Simulate: asic_unavailable"{
"error": {
"type": "asic_unavailable_error",
"code": "asic_unavailable",
"message": "Simulated: ASIC's database is not available. Retry after 300 seconds.",
"param": null,
"asicCode": "ZZ51",
"requestId": "req_01J8ZKK9L4M8N2",
"docUrl": "https://asicapi.dev/docs/errors#asic_unavailable"
}
}The header is ignored on live keys. Simulated responses carry the same headers as real ones (Retry-After on 429 and 503), so retry logic can be tested end to end.
Moving to production
- Create a live key and enable the products and jurisdictions you need.
- Swap the key. No URL or code changes are required.
- Check
meta.billablein your logs for the first live purchases and orders so you know which requests incur fees. Reads stay free. - Set an
X-Client-Referenceon purchase and order requests so your invoice lines up with your own records. - Remember that sandbox extracts do not carry over: the first live section read for a company returns
402 extract_requireduntil you purchase a live extract.
Related
Rate limits and ASIC availability
asicapi rate limits per API key, the RateLimit headers, how to handle 429 and 503 responses with backoff, ASIC maintenance windows, and caching guidance.
Webhooks for orders and offline searches
Receive order.ready, order.failed and offline_search.ready events from asicapi, verify the HMAC-SHA256 signature, and handle retries idempotently.