Business lookups (KYB)

Look up a business by ABN or ACN, confirm it against ASIC, and trace who owns it.

Before you begin

You need an access token and your partner id. See Authentication and first request.

A KYB lookup tells you who to verify. It does not verify anyone. Once you have the owner list, run Verification on the individuals.

Submit a lookup

POST /v1/business-lookups
X-Partner-Id: YOUR_PARTNER_ID
Content-Type: application/json

{ "abn": "51824753556" }

Supply an ABN or an ACN. The call returns 202 immediately with a lookupRequestId. The resolved owner list arrives asynchronously in the business-lookup.completed webhook. Correlate on that id.

Choosing the depth

scope controls what runs. Confirming the company exists on ASIC is separate from tracing who owns it.

scope What runs
FULL
default
ASIC organisation verification and the multi-level UBO report.
ASIC_ONLY ASIC organisation verification only. It does not run the multi-level UBO report, but the register result can still include directors in individuals[]. Use each party's role and partyCounts.
UBO_ONLY Multi-level UBO and ownership report only.

Omitting scope is the same as FULL. The selected scope is returned by GET /v1/business-lookups/{id}.

Pick ASIC_ONLY when you already know the owners and only need the company confirmed. Pick UBO_ONLY when the company is already confirmed and you only need the ownership tree.

Reading the result

The business-lookup.completed webhook tells you the lookup finished and carries one individuals[] entry per discovered owner.

{
  "type": "business-lookup.completed",
  "lookupRequestId": "3f0c…",
  "entity": { "name": "Acme Pty Ltd", "type": "COMPANY" },
  "individuals": [{ "idvEntityId": "idv_9a71…" }]
}

The webhook entries carry only an idvEntityId. Owner names and roles are left out of it deliberately, for data minimisation. The array is always present even when empty, so Array.isArray consumers do not have to special-case it.

If you need the names and roles, pull them from the authenticated endpoint. They are on the record, just not in the webhook:

GET /v1/business-lookups/{id}
X-Partner-Id: YOUR_PARTNER_ID

This is also the polling fallback if you do not subscribe to the webhook. The row must be owned by you.

{
  "status": "COMPLETED",
  "scope": "ASIC_ONLY",
  "partyCounts": {
    "beneficialOwners": 0,
    "directors": 2,
    "officers": 0,
    "total": 2
  },
  "individuals": [
    { "role": "DIRECTOR", "idvEntityId": "idv_9a71…" }
  ]
}

uboCount is retained for compatibility, but historic values can count directors as well as UBOs. Use partyCounts.beneficialOwners for a UBO total and partyCounts.directors for the ASIC finding.

entity.name is the ASIC registered name, falling back to the ABR name. For a sole trader that is a natural person's name, because that is what the register holds. Treat it as personal information and handle it under the same controls as the individuals.

Chaining into verification

Bind a completed FULL or UBO_ONLY lookup, and Admiin creates one individual per discovered owner:

{ "mode": "AUSTRAC_CDD", "lookupRequestId": "3f0c…" }

Or bind a chosen subset by listing their ids:

{
  "mode": "AUSTRAC_CDD",
  "lookupRequestId": "3f0c…",
  "individuals": [{ "idvEntityId": "idv_9a71…" }]
}

You do not need names to do this. idvEntityId is what links the owner the register found to the person you verify.

An ASIC_ONLY lookup cannot be bound automatically. It confirms the organisation and may return directors for display, but it does not establish the beneficial-ownership structure. Create deliberate manual verification parties instead; attempting to bind the lookup returns 400 VALIDATION_ERROR at /lookupRequestId.

A verification created from a lookup carries the register record, so it is treated as authoritative: the request goes to READY_TO_SEND rather than sitting in UBO_REVIEW. It is also the only way the entity report can print registry identity. A hand-built request renders an explicit "register data not available" note instead.

Curate the list before you submit it. Nothing forces you to verify every owner the report returned.

Rendering registry and ownership views

Read company facts from GET /v1/business-lookups/{id}/registry and the tree from GET /v1/business-lookups/{id}/ownership. The three timestamps answer different questions:

  • updatedAt — when the lookup record last changed
  • structureAsOf — when the ownership structure was determined
  • retrievedAt — when the registry panel was read

A successful response does not prove a complete tree. Show a high completeness state only when ownershipSource is AVAILABLE, complete is true, truncated is false and unlinkedOwners[] is empty. Show partial when blocked nodes, unlinked owners or truncation are present. Show unknown when traversalComplete is null, the reason is UNKNOWN, no graph exists or the source is unavailable.

The lookup identifies register parties; it does not verify their identities. To show a Verified status, read the later verification request and join the person by idvEntityId. Treat only PASSED and MANUALLY_PASSED as verified.

A live ownershipSource: AVAILABLE response includes the compliance-relevant structured names, dates of birth, addresses and screening summary returned by the live read. Verification provider names, internal request/check identifiers and raw provider payloads are removed. Identity-document and biometric evidence remains on the verification evidence endpoints. Cache a response for the current page or session to conserve the per-lookup daily read budget.

A refresh is a new paid POST /v1/business-lookups. Re-reading the registry or ownership routes does not determine a fresh structure, so show the price before starting a refresh.

When the registers hold nothing

A trust's controlling parties are exactly what ASIC and the ABR cannot tell you. A lookup on a trust returns nothing useful. That is the register being complete, not the lookup failing.

For a trust, read the parties out of the deed instead. See Trust deed analysis, then build the verification from the parties it extracts and confirm the structure yourself.

Billing

A lookup is billed to your partner account by default. To bill your own customer instead, pass contactId and see Customer billing.

If the billing gate blocks the call you get PAYMENT_METHOD_REQUIRED, CONTACT_BILLING_BLOCKED or CONTACT_INVALID. No lookup runs and no charge is written.