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 |
|---|---|
FULLdefault |
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 directors returned in the
parent lookup roster. In a FULL lookup, directors may
appear only as OFFICEHOLDING edges in the ownership
graph. Count distinct person nodes connected by edges with
role: DIRECTOR when displaying all known directors.
A completed ASIC_ONLY lookup returns
ownership: null and
reason: SCOPE_NOT_INCLUDED from the ownership route. A
completed UBO_ONLY lookup returns
registryUnavailable: true and the same reason from the
registry route. Neither response runs a live read for the excluded
panel. A lookup with no scope is a legacy
FULL lookup.
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.
For ABNs that return people in Demo, including a company suitable
for the FULL ownership flow, see
Demo test data.
Each lookup is billed for its selected scope.
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 provided test company AFFINITY SAILING PTY LTD returned three
direct shareholders at 33.33% each in a live demo
FULL read. Its traversal completeness was unknown and
indirect ownership was not identified. The UI must show those actual
values, rather than the two-shareholder arrangement or
high-confidence badge in an illustrative design.
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.