# AFS Authorised Representative Check — ASIC Bulk Screening (`malekh/afs-authorised-representative-check-asic`) Actor

Check names against ASIC's AFS Authorised Representative and Credit Representative registers. The appointing licensee is named, not just numbered, and every appointment is labelled current or ceased — 85% of ASIC's own "Current" file is ceased appointments.

- **URL**: https://apify.com/malekh/afs-authorised-representative-check-asic.md
- **Developed by:** [Malek H](https://apify.com/malekh) (community)
- **Categories:** Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.01 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## AFS Authorised Representative Check — ASIC Authorised & Credit Representative Screening

Check any name against **ASIC's AFS Authorised Representative register** and
**Credit Representative register**, get the **appointing licensee named**, and
get a straight answer to the question that matters: *is this appointment live
today?*

Background-screening vendors sell this as two separate manual products at about
**A$36 per name each**, with a one-day turnaround. This Actor answers both
registers for a fraction of that, in seconds, in bulk, from ASIC's own published
data.

***

### The thing almost every AFS authorised representative search gets wrong

ASIC publishes the AFS Authorised Representative dataset under the label
**"Current"**. It is not a list of current appointments. It is the **full
appointment history with a status column**.

Measured on the 2026-07 release:

| | rows |
|---|---|
| Total appointments in the "Current" file | **362,206** |
| Status **Ceased** | **309,807** (85.5%) |
| Status **Current** | 52,399 |

So a tool that answers *"found on the AFS Authorised Representative register"*
is wrong about currency roughly **five times out of six** — and wrong in the
direction that reports someone as authorised to provide financial services years
after ASIC records that they stopped.

Every match this Actor returns carries `isCurrent`, `asicStatus`, `startDate`
and `endDate`. Set `statusFilter` to `current` and you get only live
appointments; set it to `ceased` and you get exactly the record you need to
verify claimed past experience.

### The two registers have opposite rules, and that is the second trap

Same regulator, same portal, same release month, opposite conventions:

| | AFS Authorised Representative | Credit Representative |
|---|---|---|
| Rows (2026-07) | 362,206 | 47,731 |
| Status column | `AFS_REP_STATUS` = Current / Ceased | **none at all** |
| End dates | on every ceased row | **blank on all 47,731 rows** |
| What the file contains | full history | current appointments only |

Apply the AFS rule to the credit file and every credit representative comes back
"status unknown". Apply the credit rule to the AFS file and 309,807 ceased
appointments read as live. This Actor gives each register its own currency rule
**and asserts that rule against the file on every run** — the day ASIC changes
either convention, the run fails loudly instead of quietly inverting an answer.

### The licensee is named, not just numbered

The registers carry only the licence *number* of the appointing licensee. That
is the least useful field on the row: nobody is screening `000226403`, they are
screening *Australian Life Insurance Distribution Pty Ltd*.

This Actor joins to ASIC's AFS Licensee and Credit Licensee registers and
returns the licensee's name — which is the whole point of the check, since what
a buyer is verifying is *who this person is authorised to act for*.

There is a trap buried in that join, and it is the reason to use this rather
than roll your own: **licence numbers are zero-padded to nine digits in the
representative files (`000226403`) and unpadded in the licensee files
(`226403`)**. Join them as published and **0 of 52,399** current appointments
resolve — every row comes back "licensee unknown", a confident, complete-looking,
entirely empty answer. After normalising, 52,387 of 52,399 resolve. The Actor
checks that ratio on every run and refuses to return results if it collapses.

***

### What you get back

One row per name you supply:

```jsonc
{
  "referenceId": "2",
  "queryName": "Godfrey, Lee",
  "queryType": "person",
  "status": "ok",
  "matchCount": 3,
  "currentAppointments": 2,
  "ceasedAppointments": 1,
  "isCurrentlyAuthorised": true,
  "matches": [
    {
      "register": "Credit Representative",
      "matchConfidence": "name_exact",
      "registerName": "GODFREY, LEE",
      "representativeNumber": "434944",
      "licenceNumber": "385325",
      "licenseeName": "SMARTLINE OPERATIONS PTY LIMITED",
      "licenseeResolved": true,
      "startDate": "2013-02-25",
      "endDate": null,
      "isCurrent": true,
      "authorisations": ["Different to Appointing Rep"]
    }
    // ... plus the ceased 2004-2005 AFS appointment, labelled ceased
  ],
  "verdict": "2 current appointment(s) on Credit Representative. ...",
  "limitations": "..."
}
```

Matches are sorted strongest claim first (`name_exact`, `organisation_exact`,
`name_partial`, `name_fuzzy`), current before ceased, so the first row is always
the one you would read first anyway.

#### A same-surname hit is never allowed to answer the question

This one was found by testing rather than reasoned about, and it is worth
stating plainly. A check on *Gary Robert Smith* — whose two appointments both
ended in 2006 — turns up **58 current appointments held by unrelated Smiths**.
Let those vote and the tool reports him as currently authorised, which is the
error that gets someone hired.

So the determination is computed from `name_exact` / `organisation_exact`
matches **only**:

| field | counts |
|---|---|
| `confirmedNameMatches`, `currentAppointments`, `ceasedAppointments`, `isCurrentlyAuthorised` | exact name matches only |
| `possibleOtherMatches`, `possibleOtherMatchesCurrent` | same surname or close spelling — shown for review, never treated as this person |

Both are returned. Nothing is hidden from a screener; the weaker tier simply
cannot move the answer. `isCurrentlyAuthorised: false` means *no current
appointment under this name* — never a claim about anyone else.

For AFS appointments you also get the **authorisations** actually granted
(financial product advice, dealing, general advice, underwriting, operating a
registered scheme, wholesale clients …), the **cross-endorsing licensees**
(`AFS_REP_CROSS_ENDORSE` is a `~`-separated list — up to six other licensees
relying on the same authorisation), and whether the representative **may appoint
sub-representatives**.

One representative number can hold several simultaneous appointments — up to
**eight** measured on the current file. All of them are returned; nothing is
collapsed to "the licensee".

### Input

```json
{
  "records": [
    { "referenceId": "1", "firstName": "Gary", "middleName": "Robert", "lastName": "Smith" },
    { "referenceId": "2", "firstName": "Lee", "lastName": "Godfrey" },
    { "referenceId": "3", "organisationName": "Deegan Marine Pty Ltd" }
  ],
  "registers": "both",
  "statusFilter": "all",
  "fuzzyThreshold": 0.88
}
```

Case, punctuation and the order of given names do not matter. ASIC stores
individuals as `SURNAME, GIVEN NAMES`; that conversion is done for you.

### It fails loudly rather than returning a confident empty result

A screening tool that answers "nothing found" because its source was broken is
worse than one that crashes. Before a single name is checked — and before
anything is billed — the run verifies that:

1. every file is present in ASIC's CKAN catalogue and resolved **at runtime**
   (the filename carries a `YYYYMM` stamp and changes monthly — a hardcoded URL
   is a time bomb);
2. the header of each file matches ASIC's published schema **column by column**;
3. the delimiter is what it should be — the AFS files are **tab-delimited
   despite being served as `.csv`**, and a default CSV reader turns 362,206 rows
   into one undivided column and silently finds nothing;
4. row counts clear their floors (250,000 AFS / 30,000 credit / 3,000 AFS
   licensees / 2,000 credit licensees);
5. the AFS status vocabulary is still exactly {Current, Ceased};
6. the credit file is still current-only, so a blank end date may still be read
   as a live appointment;
7. at least 95% of current AFS appointments still resolve to a named licensee —
   the zero-padding canary;
8. every dataset was republished within the last 100 days.

If any check fails the run stops with the reason. **Nothing is charged for a run
that could not answer**, and a record with no usable name comes back
`status: "error"` — *treat as unchecked, not as clear* — and is not billed.

### Honest limits — read before you rely on this

- **A name match is not an identity match.** ASIC publishes no date of birth on
  these registers. Confirm the representative number and licensee before acting;
  the `verifyAt` field links to ASIC Connect.
- **A no-match is not a clearance.** ASIC records a representative under the
  name held at the time of appointment. A former name or a different spelling
  will not be found.
- **This is not a Financial Advisers Register check.** The FAR is a separate,
  smaller register covering personal advice on relevant financial products to
  retail clients. This Actor covers the AFS Authorised Representative and Credit
  Representative registers — the two that vendors price per name.
- **It is not a banned-and-disqualified check**, not a criminal record check and
  not a bankruptcy check. Being on the representative register says a licensee
  appointed you; it says nothing about enforcement action.
- The data is a monthly snapshot published by ASIC, not a live feed. The exact
  release date of every file used is returned on each row in `sourceReleases`.

### Source and licence

ASIC's AFS Authorised Representative, Credit Representative, AFS Licensee and
Credit Licensee datasets, published on **data.gov.au** under
**CC BY 3.0 AU**. No login, no API key, no scraping — the Actor reads the
published files through the CKAN API.

Not affiliated with or endorsed by ASIC.

# Actor input Schema

## `records` (type: `array`):

One entry per person or company. For a person pass {"firstName": "Neeraj", "lastName": "Kumar"} — middleName is optional and improves precision. For a company pass {"organisationName": "Acme Advice Pty Ltd"}. Add "referenceId" and it is echoed onto the output row, including on rows that could not be checked, so results join straight back onto your list. Case, punctuation and the order of given names do not matter; ASIC stores individuals as "SURNAME, GIVEN NAMES" and that conversion is done for you. A record with no usable name is returned with status "error" and is NOT billed.

## `registers` (type: `string`):

"both" (default) searches the AFS Authorised Representative register and the Credit Representative register — the two registers background-check vendors sell as separate per-name products. "afs" is the Corporations Act financial-services register only; "credit" is the National Credit Act register only.

## `statusFilter` (type: `string`):

"all" (default) returns current and ceased appointments, each labelled. "current" returns only appointments live today — use this when you only want to know whether someone is authorised right now. "ceased" returns only ended appointments, which is how you verify claimed past experience. ASIC's own "Current" file is really the full appointment history: 85% of its rows are ceased, so this filter is doing real work.

## `fuzzyThreshold` (type: `number`):

How close a spelling has to be before a near-miss is reported, from 0.5 (loose, more false positives) to 1.0 (exact spellings only). Default 0.88. Exact and partial matches are always returned regardless of this setting; it only controls the extra fuzzy tier.

## `maxRecords` (type: `integer`):

Safety cap on how many names one run will screen, so an oversized list cannot run up an unexpected bill. Names beyond the cap are skipped and are not billed.

## Actor input object example

```json
{
  "records": [
    {
      "referenceId": "1",
      "firstName": "Gary",
      "middleName": "Robert",
      "lastName": "Smith"
    },
    {
      "referenceId": "2",
      "firstName": "Lee",
      "lastName": "Godfrey"
    },
    {
      "referenceId": "3",
      "organisationName": "Deegan Marine Pty Ltd"
    }
  ],
  "registers": "both",
  "statusFilter": "all",
  "fuzzyThreshold": 0.88,
  "maxRecords": 500
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "records": [
        {
            "referenceId": "1",
            "firstName": "Gary",
            "middleName": "Robert",
            "lastName": "Smith"
        },
        {
            "referenceId": "2",
            "firstName": "Lee",
            "lastName": "Godfrey"
        },
        {
            "referenceId": "3",
            "organisationName": "Deegan Marine Pty Ltd"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("malekh/afs-authorised-representative-check-asic").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "records": [
        {
            "referenceId": "1",
            "firstName": "Gary",
            "middleName": "Robert",
            "lastName": "Smith",
        },
        {
            "referenceId": "2",
            "firstName": "Lee",
            "lastName": "Godfrey",
        },
        {
            "referenceId": "3",
            "organisationName": "Deegan Marine Pty Ltd",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("malekh/afs-authorised-representative-check-asic").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "records": [
    {
      "referenceId": "1",
      "firstName": "Gary",
      "middleName": "Robert",
      "lastName": "Smith"
    },
    {
      "referenceId": "2",
      "firstName": "Lee",
      "lastName": "Godfrey"
    },
    {
      "referenceId": "3",
      "organisationName": "Deegan Marine Pty Ltd"
    }
  ]
}' |
apify call malekh/afs-authorised-representative-check-asic --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=malekh/afs-authorised-representative-check-asic",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/121d6JC7RUgTM9BnR/builds/5sQuJAr37fXxwOO3r/openapi.json
