# Malaysia Open Data Studio — Gov Data Joins (`subimpact/my-open-data-studio`) Actor

Value layer on Malaysia's official open data API (data.gov.my): cross-dataset joins (population x income x CPI by state), CSV/JSON/XLSX delivery, webhooks, AI-ready output with CC BY 4.0 attribution.

- **URL**: https://apify.com/subimpact/my-open-data-studio.md
- **Developed by:** [subimpact](https://apify.com/subimpact) (community)
- **Categories:** AI, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 joined pulls

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Malaysia Open Data Studio — Gov Data Joins

**Cross-dataset joins on Malaysia's official open data (data.gov.my), delivered as clean CSV / JSON / XLSX — with AI-ready output and CC BY 4.0 attribution built in.**

This Actor is a **value layer** on the official [data.gov.my](https://data.gov.my) API. It does not scrape the website and it does not charge for data that is already free — it sells the *work*: joining, cleaning, and packaging government open data for people who need it in a usable shape.

### Why use this Actor

- **No scraping.** Uses the official, keyless API (`api.data.gov.my`) — stable, licensed, CC BY 4.0.
- **Real joins, not raw dumps.** 11 ready-made preset bundles + custom joins (pick your own datasets and keys).
- **Drop-in for spreadsheets.** CSV / XLSX output opens directly in Excel, Google Sheets, or Numbers.
- **AI-ready.** Every run can emit a JSON Schema + data dictionary + sample rows — designed for LLM/RAG ingestion.
- **Attribution handled.** CC BY 4.0 source metadata is attached to every output, so you stay compliant with zero effort.
- **Webhooks.** Push results straight to your pipeline (3 retries, backoff).

### Presets

All presets emit one flat, joined table. `(state, year)` joins include 16 states / federal territories (incl. W.P. KL, Labuan, Putrajaya).

**B1 — Economy by State** — population × household income × CPI, joined on `(state, year)`.

- `population_thousands`, `income_mean_rm`, `income_median_rm`, `cpi_annual_2010_100`

**B2 — Demography by State** — population × births × deaths × crime, joined on `(state, year)`.

- `population_thousands`, `births`, `birth_rate_per_1000`, `deaths`, `death_rate_per_1000`, `crimes_total`

**B3 — Labour Market & Mobility** — labour force (quarterly, annualised) × passport issuances, joined on `(state, year)`.

- `labour_force_thousands`, `employed_thousands`, `unemployed_thousands`, `participation_rate_pct`, `unemployment_rate_pct`, `passports_issued`

**B4 — Prices & Inflation (National)** — fuel prices (weekly, annualised) × headline CPI × core CPI, joined on `(year)`.

- `fuel_ron95_rm`, `fuel_ron97_rm`, `fuel_diesel_rm`, `cpi_headline_2010_100`, `cpi_core_2010_100`

**B5 — Health & Pandemic by State** — COVID-19 cases × vaccine registrations × organ pledges, joined on `(state, year)`.

- `covid_new_cases`, `covid_active_cases`, `covid_recoveries`, `vax_registrations`, `organ_pledges`

**B6 — Public Transport Ridership (National)** — rail & bus ridership × KTMB services, joined on `(year)`.

- `ridership_lrt_ampang`, `ridership_lrt_kelana_jaya`, `ridership_mrt_kajang`, `ridership_mrt_putrajaya`, `ridership_monorail`, `ridership_komuter`, `ridership_ets`, `ridership_intercity`, `ridership_shuttle_tebrau`, `ridership_bus_rkl`, `ridership_ktmb_total`

**B7 — Education by State** — schools × teachers × enrolment × upper-secondary completion, joined on `(state, year)`.

- `schools_total`, `teachers_total`, `students_total`, `completion_rate_upper_secondary_pct`

**B8 — Tourism & Arrivals (National)** — monthly international arrivals (total, female, male), annualised by `(year)`.

- `arrivals_total`, `arrivals_female`, `arrivals_male`

**B9 — Agriculture & Commodities by State** — crops × fish landings × timber × minerals, joined on `(state, year)`.

- `crop_planted_area_ha`, `crop_production_tonnes`, `fish_landings_tonnes`, `timber_production_m3`, `mineral_production_tonnes`

**B10 — Public Safety by State** — crime × prisoners × drug addicts, joined on `(state, year)`.

- `crimes_total`, `prisoners_total`, `drug_addicts_total`

**B11 — Healthcare Capacity by State** — hospital beds × healthcare staff × STD cases × maternal deaths, joined on `(state, year)`.

- `hospital_beds_total`, `healthcare_staff_total`, `std_cases_total`, `maternal_deaths`, `maternal_death_rate_per_100k`

**Custom join** — bring your own 2–6 data.gov.my dataset ids, choose join keys (`year` auto-extracts from `date`, or raw fields like `state`/`district`), join type (`inner`/`left`), optional aggregation (`sum`/`mean`), and API filters. Example: household income × poverty by district (480 rows, 2019–2024).

### Input

| field | type | default | description |
|---|---|---|---|
| `preset` | enum | `B1` | `B1`–`B11` or `custom` |
| `customDatasets` | string list | — | custom join: dataset ids (2–6) |
| `customKey` | string list | `["state","year"]` | custom join: key columns (`year` = date field's year) |
| `customJoinType` | enum | `inner` | `inner` / `left` |
| `customParams` | string | — | JSON object of extra API params (e.g. `{"filter": "overall@division"}`) |
| `customAgg` | enum | `none` | `none` / `sum` / `mean` |
| `format` | enum | `json` | `json` / `csv` / `xlsx` |
| `webhookUrl` | string | — | POST the result file here after the run (optional) |
| `aiReady` | bool | `true` | Emit JSON Schema + dictionary + samples |
| `includeAttribution` | bool | `true` | Attach CC BY 4.0 metadata sidecar |

### Output

Key-value store:

- `<preset>_join.<json|csv|xlsx>` — the joined table
- `<preset>_ai_ready.json` — schema + data dictionary + sample rows (LLM/RAG)
- `<preset>_attribution.json` — CC BY 4.0 source metadata
- `<preset>_verification.json` — row count, year range, state coverage, source rows

Dataset (default) — run verification record.

### Cost

**$0.00999 per run (pay-per-event, one `joined-pull` charge ≈ $9.99 / 1,000 pulls).** The underlying data comes from Malaysia's official free API (data.gov.my, CC BY 4.0) — you pay for the join + packaging, not the data. Apify compute is negligible for this size of run (~$0.002).

### Roadmap

- Scheduled delta runs driven by `next_update` (subscription plans $5–25/mo)
- Drift monitoring alerts (we flag stale government metadata)
- Google Sheets / BigQuery / S3 push

### Attribution

Malaysia Open Data — [data.gov.my](https://data.gov.my). Licensed under **CC BY 4.0**. See `<preset>_attribution.json` in every run output.

# Actor input Schema

## `preset` (type: `string`):

Join bundle. B1 = Economy by State. B2 = Demography by State. B3 = Labour Market & Mobility. B4 = Prices & Inflation. B5 = Health & Pandemic. B6 = Public Transport Ridership. B7 = Education by State. B8 = Tourism & Arrivals. B9 = Agriculture & Commodities. B10 = Public Safety. B11 = Healthcare Capacity. custom = bring your own dataset ids.

## `customDatasets` (type: `array`):

For preset=custom: list of data.gov.my catalogue ids to join (2-6). Leave empty to use a preset.

## `customKey` (type: `array`):

For preset=custom: key parts to join on. Use 'year' (extracted from the date field) or raw field names like state, district. All datasets must share these keys.

## `customJoinType` (type: `string`):

inner keeps only keys present in every dataset; left keeps all keys from the first dataset.

## `customParams` (type: `string`):

For preset=custom: JSON object of extra API params applied to every dataset, e.g. {"filter": "overall@division"}.

## `customAgg` (type: `string`):

none = keep raw rows (last value per key). sum = aggregate numeric values per key. mean = average numeric values per key.

## `format` (type: `string`):

File format delivered to the key-value store (dataset records are always JSON).

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

POST the result file to this URL after the run (3 retries with backoff). Leave empty to skip.

## `aiReady` (type: `boolean`):

Also emit JSON Schema + data dictionary + sample rows for LLM/RAG ingestion.

## `includeAttribution` (type: `boolean`):

Attach source/licence metadata sidecar to every output.

## Actor input object example

```json
{
  "preset": "B1",
  "customKey": [
    "state",
    "year"
  ],
  "customJoinType": "inner",
  "customAgg": "none",
  "format": "json",
  "aiReady": true,
  "includeAttribution": true
}
```

# 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("subimpact/my-open-data-studio").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("subimpact/my-open-data-studio").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 '{}' |
apify call subimpact/my-open-data-studio --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=subimpact/my-open-data-studio",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/EVHrtzSQCbCtjupSk/builds/t1YiMrg2CAhbUHoxy/openapi.json
