# Singapore ACRA Corporate Registry - Delta Monitor (`stefano_seggio/singapore-acra-registry-monitor`) Actor

ACRA Singapore UEN delta monitor: tracks the corporate register (Pte Ltd, sole props, LLPs) via data.gov.sg for new incorporations, status changes (Struck Off, In Liquidation, Dissolved), SSIC/address updates. Filter by UEN, SSIC code, or status. Pay-per-event: billed only for what changed.

- **URL**: https://apify.com/stefano\_seggio/singapore-acra-registry-monitor.md
- **Developed by:** [Stefano Seggio](https://apify.com/stefano_seggio) (community)
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $30.00 / 1,000 new listing or status changes

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/actors/running/actors-in-store.md#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

## Singapore ACRA Corporate Registry Monitor

#### Singapore's corporate register changes daily. Most people find out weeks later.

If you do business with, invest in, or run compliance checks on Singapore-registered entities, your only way to know a company went from Live to Struck Off, In Liquidation, or Dissolved is to manually re-check ACRA yourself, one UEN at a time. **This Actor solves that**: it delta-tracks the entire Singapore corporate register — Pte Ltd companies, sole proprietorships, and LLPs — and tells you the moment a status actually changes.

***

### Why this outperforms a standard scraper

- **Delta tracking, not re-scraping.** Every entity is fingerprinted on every run against data.gov.sg's official ACRA dataset. Unchanged entities are never re-delivered — and never billed.
- **Pay only for what's new.** A new incorporation or a real status change (Live → Struck Off, In Liquidation, Dissolved, Amalgamated) costs $0.03. A non-status update — name, address, SSIC classification, officer count, former name, or audit firm — costs $0.01. An unchanged entity costs nothing.
- **Corporate identity verification, not just a name list.** Every record carries the UEN, current SSIC classification, and status history — the actual identifiers a compliance or KYB check needs, not just a company name string.

### See it before you trust it

```json
{
  "uen": "201912345K",
  "event_type": "STATUS_CHANGE",
  "entity_name": "Example Trading Pte. Ltd.",
  "entity_type": "Pte Ltd",
  "previous_status": "Live",
  "current_status": "Struck Off",
  "ssic_code": "46900",
  "status_changed_date": "2026-09-10"
}
```

Notice `uen` — that's the actual government-issued identifier, not a scraped name string you'd need to re-verify yourself. And `previous_status` → `current_status` is the exact transition, not just a snapshot.

### Zero-risk trial

Unchanged runs cost **$0.00**. Run it once against real data before you commit to anything:

```bash
curl -X POST "https://api.apify.com/v2/acts/ht22I1rCH3Ah9QGnM/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"onlyNew": true, "maxItemsPerRun": 50}'
```

```python
import requests

response = requests.post(
    "https://api.apify.com/v2/acts/ht22I1rCH3Ah9QGnM/run-sync-get-dataset-items",
    params={"token": "<YOUR_API_TOKEN>"},
    json={"onlyNew": True, "maxItemsPerRun": 50},
)
records = response.json()
print(f"{len(records)} records returned")
```

```javascript
const response = await fetch(
  "https://api.apify.com/v2/acts/ht22I1rCH3Ah9QGnM/run-sync-get-dataset-items?token=<YOUR_API_TOKEN>",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ onlyNew: true, maxItemsPerRun: 50 }),
  }
);
const records = await response.json();
console.log(`${records.length} records returned`);
```

### Pricing

| Event | What it means | Price |
|---|---|---|
| New Listing or Status Change | A genuinely new entity, or an entity whose status changed (e.g. Live → Struck Off, In Liquidation, Dissolved, Amalgamated). | $0.03 |
| Update | Name, address, SSIC classification, officer count, former name, or audit firm changed — no status change. | $0.01 |

Actor-start fee: $0.00005/GB-memory (one-time per run, not per record).

### What you get on every record

- UEN (the official Singapore entity identifier)
- Entity type: Pte Ltd, sole proprietorship, or LLP
- Full status history transition (previous → current)
- SSIC classification code
- Former names, where applicable
- Delta classification so you never re-process an unchanged entity

### Input parameters

| Field | Type | Description | Default |
|---|---|---|---|
| `uen` | string | Filter to a specific UEN, if you only need to watch one entity. | none (watches all) |
| `ssicCode` | string | Filter to entities under a specific SSIC classification. | none |
| `status` | string | Filter to entities currently in a specific status. | none |
| `maxItemsPerRun` | integer | Caps how many entities are processed in one run. | 50 |
| `onlyNew` | boolean | When true, only new/status-change events are returned. | true |

### Source & reliability

Source is data.gov.sg's official ACRA dataset — Singapore's government open-data platform, not a scraped or reverse-engineered feed. Runs on the same delta-engine pattern behind this operator's whole fleet: canonicalize, fingerprint, persist state across runs, and classify every record as new, changed, or unchanged before it's ever billed.

# Actor input Schema

## `shardSelection` (type: `array`):

ACRA's data.gov.sg register is split into 27 files by the entity name's first letter (A-Z, plus 'Others' for names starting with a digit/symbol). Select a subset to bound run time/cost, or leave all selected to monitor the full ~2.1M-entity register.

## `onlyNew` (type: `boolean`):

When true (recommended, and the only free-of-charge default), only NEW\_LISTING, STATUS\_CHANGE, and UPDATED events are delivered - never a snapshot of unchanged or first-run-baseline entities. When false, every entity is delivered every run, including BASELINE\_SNAPSHOT (first-run) and SNAPSHOT\_NO\_DIFF (unchanged) rows - useful for a full audit/export, but on a first run against all 27 shards this delivers roughly 2.1 million uncharged rows to your dataset.

## `eventTypes` (type: `array`):

Restricts which of the three charged event types are delivered. Leave empty to deliver all three. Has no effect on BASELINE\_SNAPSHOT/SNAPSHOT\_NO\_DIFF, which are controlled solely by 'onlyNew'.

## `ssicCodeFilter` (type: `array`):

Deliver only entities whose primary or secondary SSIC code starts with one of these prefixes - e.g. \["62"] for the whole Computer Programming/IT division (62011, 62020, 62090, ...), or \["62011"] for an exact code. Matching happens at delivery time only: every entity is still tracked internally regardless of this filter, so an entity that changes INTO your filtered SSIC range is correctly reported as UPDATED/STATUS\_CHANGE the moment it does, not missed because it didn't match previously. Leave empty to deliver all industries.

## `entityStatusFilter` (type: `array`):

Deliver only entities whose CURRENT status exactly matches one of these (case-insensitive) - e.g. \["Struck Off", "In Liquidation - Compulsory Winding Up (Insolvency)"] to watch only distressed/exited entities. Real status strings observed in the live register (2026-09-11): "Live", "Live Company", "Struck Off", "Terminated", "Cancelled", "Cancelled (Non-Renewal)", "Ceased Registration", "Amalgamated", "Dissolved - Members Voluntary Winding Up", "Dissolved - Creditors Voluntary Winding Up", "Dissolved - Compulsory Winding Up (Insolvency)", "In Liquidation - Members voluntary winding up", "In Liquidation - Compulsory Winding Up (Insolvency)". This list is not guaranteed exhaustive - ACRA's own register may use additional status strings not yet observed. As with the SSIC filter, matching is delivery-time only; internal tracking always covers every status. Leave empty to deliver all statuses.

## `maxItems` (type: `integer`):

Stops the run once this many records have been pushed (and charged, where applicable). Entities not yet reached when the limit is hit are simply re-evaluated fresh next run - nothing is lost or double-counted. Leave unset for no limit (a full-register run can deliver a large number of BASELINE\_SNAPSHOT rows on its very first execution if onlyNew=false).

## `deltaStateName` (type: `string`):

Names the persistent Key-Value Store this run's delta memory lives in. Use a distinct name per independent schedule/configuration if you run this Actor more than one way (e.g. one schedule per shard subset) so they don't share baseline progress. Leave as 'default' for a single schedule.

## `resetState` (type: `boolean`):

When true, ignores all previously-remembered entities for the selected shards and re-baselines from scratch (every entity becomes a fresh, uncharged BASELINE\_SNAPSHOT again). Use only to deliberately restart monitoring - this will suppress NEW\_LISTING/STATUS\_CHANGE/UPDATED detection for one run per affected shard.

## `watchlistUens` (type: `array`):

A bounded list of specific UENs to re-check via ACRA's own real-time Business Profile API (see 'ACRA Business Profile API key' below) in addition to the monthly bulk extract - use this for a small number of high-priority counterparties where a fresher-than-monthly check matters. Requires 'ACRA Business Profile API key' to be set.

## `acraBusinessProfileApiKey` (type: `string`):

Required only when 'Watchlist UENs' is non-empty. Bring-your-own-key: obtain a paid subscription key from ACRA's own API Marketplace (Entity Information Query / EIQ product, launched 18 Nov 2025) - this Actor never attempts to create that subscription on your behalf. Never logged or persisted beyond this run. Note: the exact response schema for this API was not independently verified during this Actor's build (it sits behind the same subscriber wall as the key itself) - see AGENTS.md before relying on BYOK enrichment in production.

## `webhookUrl` (type: `string`):

A Slack Incoming Webhook URL, or any HTTPS endpoint that accepts a JSON POST (e.g. a Make/n8n/Zapier catch-hook), to receive a formatted alert the moment a STATUS\_CHANGE event is detected (the event type a compliance team actually escalates on). This is independent of, and does not replace, Apify's own platform-level webhook system, which you can configure separately in the Apify Console for the other event types.

## Actor input object example

```json
{
  "shardSelection": [
    "A"
  ],
  "onlyNew": true,
  "ssicCodeFilter": [],
  "entityStatusFilter": [],
  "maxItems": 25,
  "deltaStateName": "default",
  "resetState": false,
  "watchlistUens": []
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("stefano_seggio/singapore-acra-registry-monitor").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("stefano_seggio/singapore-acra-registry-monitor").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call stefano_seggio/singapore-acra-registry-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,stefano_seggio/singapore-acra-registry-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ht22I1rCH3Ah9QGnM/builds/3Dz0XbqBK25BAgwIg/openapi.json
