# GeBIZ Singapore Government Tender Awards & Supplier Analytics (`zhucl1006/gebiz-singapore-tender-awards`) Actor

Search Singapore government tender awards (GeBIZ, via official data.gov.sg open data) by keyword, agency, supplier, date and amount. Clean, de-duplicated records plus agency/supplier spend rankings.

- **URL**: https://apify.com/zhucl1006/gebiz-singapore-tender-awards.md
- **Developed by:** [leo zhu](https://apify.com/zhucl1006) (community)
- **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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## GeBIZ Singapore Government Tender Awards & Supplier Analytics

Search **Singapore government procurement awards** (tenders and quotations awarded through GeBIZ) and get **clean, de-duplicated, analysis-ready records** plus **spend rankings by agency, supplier or fiscal year** — in seconds, without scraping.

The data comes from the official open dataset **"Government Procurement via GeBIZ"** published by the **Ministry of Finance (MOF)** on [data.gov.sg](https://data.gov.sg/datasets/d_acde1106003906a75c3fa052592f2fcb/view) under the **Singapore Open Data Licence v1.0**, which permits commercial use with attribution.

### What can you use it for?

- **Sales & business development** – find which agencies buy what you sell (cleaning, IT, construction, consultancy...) and how much they spend.
- **Competitor intelligence** – see every award won by a competitor, with amounts, agencies and dates.
- **Market sizing** – total awarded value per agency, supplier or Singapore fiscal year (April–March).
- **Pricing benchmarks** – median / average / max award amounts for comparable tenders.
- **Due diligence & journalism** – check a company's public-sector track record.

### Features

- 🔎 Filter by **keywords** (any/all, matched against tender description and tender number), **agency**, **supplier**, **tender numbers**, **award date range** and **awarded amount range**.
- 🧹 **Clean output**: ISO dates (`YYYY-MM-DD`), numeric amounts in SGD, trimmed text, upper-cased tender numbers, `Unknown` suppliers converted to `null`, stable `recordId`, exact-duplicate removal.
- 📊 **Spend analytics (unique feature)**: rank suppliers, agencies, agency × supplier pairs or fiscal years by total awarded value, with award count, tender count, average / median / max award, share of total, first / last award date and the top 5 counterparties for each group.
- ⚡ Fast and light: one bulk download of the full official dataset (≈18,000 rows), typically **5–10 seconds** per run on 256 MB memory.
- 🔁 Resilient: automatic fallback from bulk download to the paginated data.gov.sg API, with retries on rate limits (HTTP 429).
- 💸 Spending-limit aware: stops pushing results when your maximum cost per run is reached.

### Input

| Field | Type | Description |
|---|---|---|
| `keywords` | array of strings | Words/phrases to search in the tender description and tender number (case-insensitive). Empty = no keyword filter. |
| `keywordMatch` | `any` / `all` | Match records containing any keyword (default) or all keywords. |
| `agencies` | array of strings | Agency names or parts of names, e.g. `Land Transport Authority`, `Ministry of Health`. |
| `suppliers` | array of strings | Supplier names or parts of names, e.g. `NCS`, `ST Engineering`. |
| `tenderNumbers` | array of strings | Exact tender/quotation numbers. |
| `dateFrom` / `dateTo` | date (`YYYY-MM-DD`) | Award date range (inclusive). |
| `minAmount` / `maxAmount` | integer (SGD) | Awarded amount range. |
| `includeNoAward` | boolean | Also include tenders closed with *no supplier awarded* (amount is `null`). Default `false`. |
| `maxItems` | integer | Maximum number of award records to output (default 1000, `0` = no limit). Summaries always use **all** matching records. |
| `sortBy` | `awardDateDesc` / `awardDateAsc` / `amountDesc` / `amountAsc` | Sort order of award records. |
| `outputMode` | `records` / `summary` / `both` | Output award records, spend summary rows, or both. |
| `summaryBy` | `supplier` / `agency` / `agencySupplier` / `fiscalYear` / `agencyFiscalYear` / `supplierFiscalYear` | How to group the spend summary. |
| `summaryTopN` | integer | Number of summary rows (ranked by total awarded value, `0` = all). |
| `dataSource` | `auto` / `bulkDownload` / `datastoreApi` | How to read data.gov.sg. `auto` is recommended. |
| `dataGovApiKey` | string (secret, optional) | Your own free data.gov.sg API key for higher rate limits. Not required. |

#### Example input

```json
{
  "keywords": ["cleaning"],
  "dateFrom": "2024-04-01",
  "maxItems": 50,
  "sortBy": "awardDateDesc",
  "outputMode": "both",
  "summaryBy": "supplier",
  "summaryTopN": 10
}
```

### Output

Results are stored in the default dataset (views: **Award records** and **Spend summary**) and can be downloaded as JSON, CSV, Excel, XML or via API. A `RUN_SUMMARY` record in the key-value store contains run statistics, dataset metadata and the attribution text.

#### Award record example

```json
{
  "recordType": "award",
  "recordId": "770ea4870ed73d19",
  "tenderNo": "NEA000ETT25000068",
  "tenderDescription": "Provision of Integrated Cleaning Services",
  "agency": "National Environment Agency",
  "awardDate": "2026-02-26",
  "awardYear": 2026,
  "sgFiscalYear": 2025,
  "tenderStatus": "Awarded to Suppliers",
  "isItemizedAward": false,
  "hasSupplier": true,
  "supplierName": "PRIMECH A & P PTE. LTD.",
  "awardedAmountSgd": 32312600.0,
  "currency": "SGD",
  "datasetLastUpdatedAt": "2026-04-26T21:48:27+08:00",
  "source": "data.gov.sg - Government Procurement via GeBIZ (Ministry of Finance)",
  "sourceUrl": "https://data.gov.sg/datasets/d_acde1106003906a75c3fa052592f2fcb/view",
  "licence": "Singapore Open Data Licence v1.0 (https://data.gov.sg/open-data-licence)"
}
```

`sgFiscalYear` follows the Singapore Government financial year (FY2025 = 1 April 2025 – 31 March 2026). `isItemizedAward` is `true` for "Awarded by Items" tenders, where one tender can be split between several suppliers (one record per supplier).

#### Spend summary row example (`summaryBy: supplier`)

```json
{
  "recordType": "summary",
  "rank": 3,
  "groupBy": "supplier",
  "groupKey": "PRIMECH A & P PTE. LTD.",
  "supplierName": "PRIMECH A & P PTE. LTD.",
  "awardCount": 3,
  "tenderCount": 3,
  "totalAwardedSgd": 62099181.0,
  "shareOfTotalPct": 8.95,
  "lastAwardDate": "2026-02-26",
  "topCounterparties": [{ "name": "National Environment Agency", "totalAwardedSgd": 32312600.0, "awardCount": 1 }]
}
```

(Abbreviated — real rows also include `averageAwardSgd`, `medianAwardSgd`, `maxAwardSgd`, `firstAwardDate`, `currency`, `source` and `licence`.)

### Data coverage and freshness

- Source: *Government Procurement via GeBIZ*, Ministry of Finance, data.gov.sg (dataset `d_acde1106003906a75c3fa052592f2fcb`).
- Coverage at the time of writing: awards from **April 2021 to March 2026**, ≈18,400 rows, 113 agencies, ≈6,100 suppliers. The dataset was last updated by MOF on 26 April 2026; every output record carries `datasetLastUpdatedAt` so you always know how fresh the data is.
- The Actor always reads the latest version published on data.gov.sg; it does not add, estimate or modify any amounts.

### Why no "open tender opportunities"?

This Actor deliberately covers **awarded** procurement only. Live opportunities are only available on the GeBIZ website, whose Terms of Use prohibit reproducing or redistributing its content without prior written permission of the operator. To keep your data use clean, this Actor uses only the official open dataset, which is licensed for commercial reuse. It does not scrape, cache or link to gebiz.gov.sg.

### Pricing

Pay-per-event pricing (planned; see the Pricing tab for current values):

- Actor start: small flat fee per run
- Award record: per record written to the dataset
- Summary row: per spend-summary row written to the dataset

Set a **maximum cost per run** in the run options; the Actor stops producing results when it is reached.

### Data source and licence (attribution)

Contains information from **Government Procurement via GeBIZ** accessed from **data.gov.sg**, which is made available under the terms of the **Singapore Open Data Licence version 1.0** (<https://data.gov.sg/open-data-licence>). Each run stores the exact attribution statement, including the access date, in the `RUN_SUMMARY` key-value store record.

If you republish or build products on the output, you must keep this attribution. This Actor is an independent tool and is **not affiliated with or endorsed by** the Ministry of Finance, GovTech, DSTA, GeBIZ or the Government of Singapore. The data is provided "as is"; please verify critical information with the official source.

### FAQ

**Do I need a data.gov.sg account or API key?** No. The dataset is public. An optional free API key only raises rate limits.

**Can I monitor a competitor or agency regularly?** Yes — schedule the Actor (e.g. monthly) with a `suppliers` or `agencies` filter and connect it to Google Sheets, Slack or webhooks via Apify integrations.

**Why do some tenders have several records?** "Awarded by Items" tenders are split between multiple suppliers; each supplier gets its own record with its own amount.

# Actor input Schema

## `keywords` (type: `array`):

Words or phrases to find in the tender description or tender number (case-insensitive substring match). Leave empty to return all awards.

## `keywordMatch` (type: `string`):

Return awards matching ANY of the keywords, or only those matching ALL of them.

## `agencies` (type: `array`):

Filter by government agency name (partial, case-insensitive), e.g. 'Land Transport Authority', 'Ministry of Education', 'Housing'.

## `suppliers` (type: `array`):

Filter by awarded supplier name (partial, case-insensitive), e.g. 'NCS', 'KPMG'.

## `tenderNumbers` (type: `array`):

Optional exact GeBIZ tender numbers, e.g. 'BCA000ETT22000021'.

## `dateFrom` (type: `string`):

Earliest award date (YYYY-MM-DD).

## `dateTo` (type: `string`):

Latest award date (YYYY-MM-DD).

## `minAmount` (type: `integer`):

Only awards with an awarded amount at or above this value.

## `maxAmount` (type: `integer`):

Only awards with an awarded amount at or below this value.

## `includeNoAward` (type: `boolean`):

Also return tenders closed with status 'Awarded to No Suppliers' (no supplier, no amount).

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

Maximum number of award records to output (0 = no limit). Summary rows are not counted.

## `sortBy` (type: `string`):

Order of award records in the output.

## `outputMode` (type: `string`):

Award records, an aggregated spend ranking, or both.

## `summaryBy` (type: `string`):

Grouping used for the spend summary: total awarded SGD, award count, distinct tenders, average/median/max award, share of total, first/last award date and top counterparties.

## `summaryTopN` (type: `integer`):

How many summary rows to output, ranked by total awarded amount (0 = all).

## `dataSource` (type: `string`):

How to read the official data.gov.sg dataset. 'Auto' uses the fast bulk CSV download and falls back to the paginated datastore API. Note: live GeBIZ opportunities are not collected because the GeBIZ website terms prohibit republishing its content.

## `dataGovApiKey` (type: `string`):

Optional. Your own free data.gov.sg API key for higher rate limits. Not required.

## Actor input object example

```json
{
  "keywords": [
    "cleaning"
  ],
  "keywordMatch": "any",
  "includeNoAward": false,
  "maxItems": 100,
  "sortBy": "awardDateDesc",
  "outputMode": "records",
  "summaryBy": "supplier",
  "summaryTopN": 50,
  "dataSource": "auto"
}
```

# 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 = {
    "keywords": [
        "cleaning"
    ],
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("zhucl1006/gebiz-singapore-tender-awards").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 = {
    "keywords": ["cleaning"],
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("zhucl1006/gebiz-singapore-tender-awards").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 '{
  "keywords": [
    "cleaning"
  ],
  "maxItems": 100
}' |
apify call zhucl1006/gebiz-singapore-tender-awards --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zhucl1006/gebiz-singapore-tender-awards"
        }
    }
}
```

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/fdk9RU5akagan4cLa/builds/aPJdoly1H2zaZOXmS/openapi.json
