# Singapore GeBIZ Tender Awards (data.gov.sg) (`knotty_mistveil/singapore-gebiz-tender-awards`) Actor

Singapore government contract awards from the official GeBIZ dataset on data.gov.sg: tender, agency, award date, supplier, amount. Filter, pay per result.

- **URL**: https://apify.com/knotty\_mistveil/singapore-gebiz-tender-awards.md
- **Developed by:** [Jason](https://apify.com/knotty_mistveil) (community)
- **Categories:** Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 result returneds

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 GeBIZ Tender Awards (data.gov.sg)

Get every Singapore government contract award as clean JSON: tender number, description, awarding agency, award date, status, winning supplier and awarded amount in SGD. The data comes from the Ministry of Finance's official **"Government Procurement via GeBIZ"** dataset on data.gov.sg, which lists tenders put out by government agencies since FY2021 and who won them. Filter by award date, keyword, agency, supplier, status and minimum amount, and pay only for the records you receive. No API key, no login, no browser automation.

**This Actor returns the official awards dataset, not live GeBIZ listings.** The GeBIZ portal itself is a bidding system whose terms of use prohibit reproducing, redistributing or even caching its contents without written permission, and its pages change without notice, so scraping it is fragile and not clearly permitted. The Ministry of Finance dataset on data.gov.sg is the authoritative, openly licensed record of what was actually awarded, to whom and for how much, which is what you need for supplier intelligence, win/loss analysis, price benchmarking and lead lists. It is refreshed about once a year, so if you need open (not yet awarded) tenders or same-week award notices, this is not the right tool.

### What you get

One record per tender-supplier pair (a tender awarded by items to three suppliers yields three records), newest award first:

- `id` - stable id `<tenderNo>:<supplier-slug>` (a numeric suffix is added if a pair ever repeats)
- `source` - `data.gov.sg/gebiz`
- `url` - the public dataset page on data.gov.sg
- `tenderNo` - GeBIZ tender number, e.g. `HDB000ETT24000004`
- `tenderDescription` - tender title as published
- `agency` - awarding agency (113 agencies: ministries, statutory boards, schools)
- `awardDate` - ISO `YYYY-MM-DD` (converted from the source's `d/m/yyyy`); `awardDateRaw` keeps the original string
- `status` - `Awarded to Suppliers`, `Awarded by Items`, `Award by interface record` or `Awarded to No Suppliers`
- `supplierName` - winning supplier (`Unknown` when awarded to no suppliers)
- `awardedAmountSgd` - awarded amount as a number in Singapore dollars
- `datasetLastUpdated` - when data.gov.sg last refreshed the dataset, so you know how fresh the data is
- `fetchedAt` - ISO timestamp of the run

The run also writes a `SUMMARY` record to the key-value store with `datasetLastUpdated`, `coverageStart`/`coverageEnd`, total rows, rows matched, rows delivered and any warnings.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `keywords` | string\[] | `[]` | Case-insensitive words/phrases matched against the tender description (and tender number). Any match passes. |
| `agencies` | string\[] | `[]` | Case-insensitive substrings matched against the agency name, e.g. `"Housing and Development Board"`, `"Health"`. |
| `suppliers` | string\[] | `[]` | Case-insensitive substrings matched against the supplier name, e.g. `"NCS"`, `"Accenture"`. |
| `statuses` | string\[] | `[]` | Case-insensitive match on `tender_detail_status`; see the four values above. Empty = all. |
| `dateFrom` | string | - | Earliest award date, `YYYY-MM-DD` (inclusive). Overrides `daysBack`. Dataset starts 2021-04-01. |
| `dateTo` | string | today | Latest award date, `YYYY-MM-DD` (inclusive). |
| `daysBack` | integer | `365` | Used when `dateFrom` is empty: awards from this many days before `dateTo`. One year by default because the dataset is refreshed about once a year. If you give neither `dateFrom` nor `dateTo`, the window is slid back so it ends at the dataset's published coverage end, which keeps a default run inside the data even between annual refreshes (the log says so). |
| `minAmount` | number | `0` | Only awards with `awardedAmountSgd` at or above this value; decimals accepted, since source amounts can be fractional. Any value above 0 also drops the zero-amount "Awarded to No Suppliers" rows. |
| `maxItems` | integer | `1000` | Stop after this many results (newest first). You are charged per result. The Store form prefills 100 for a cheap first run. |

Example: all IT-related awards above S$1M won by any supplier in 2025:

```json
{
  "keywords": ["software", "cloud", "IT ", "system"],
  "dateFrom": "2025-01-01",
  "dateTo": "2025-12-31",
  "minAmount": 1000000,
  "maxItems": 500
}
```

### Output example

A real record from a run on 2026-09-07 (window from 2024-01-01, status `Awarded to Suppliers`, `minAmount` 1000):

```json
{
  "id": "CDVHQ0ETT25000022:mie-tech-engineering-construction-pte-ltd",
  "source": "data.gov.sg/gebiz",
  "url": "https://data.gov.sg/datasets/d_acde1106003906a75c3fa052592f2fcb/view",
  "tenderNo": "CDVHQ0ETT25000022",
  "tenderDescription": "Invitation to Tender for the Proposed FAM@FSC and FFLC at Blk 123, 128 and 131 Bedok Reservoir Road Singapore",
  "agency": "Ministry of Social and Family Development - Ministry Headquarter",
  "awardDate": "2026-03-31",
  "awardDateRaw": "31/3/2026",
  "status": "Awarded to Suppliers",
  "supplierName": "MIE-TECH ENGINEERING & CONSTRUCTION PTE LTD",
  "awardedAmountSgd": 862187,
  "datasetLastUpdated": "2026-04-26T21:48:27+08:00",
  "fetchedAt": "2026-09-07T06:09:51.996Z"
}
```

### Pricing

Pay per result: **US$0.002 per record, i.e. US$2 per 1,000 results.** You are charged only for records actually delivered to the dataset (nothing for empty runs), and the run stops automatically when your Apify spend limit is reached. The whole dataset (about 18,500 records covering five financial years) costs under US$40; one financial year is roughly 3,500 to 4,000 records, i.e. US$7 to US$8. Apify's free plan limits how much you can run per month; see the Apify pricing page for current limits.

### Data source and licence

- Dataset: [Government Procurement via GeBIZ](https://data.gov.sg/datasets/d_acde1106003906a75c3fa052592f2fcb/view), published by the Ministry of Finance on data.gov.sg (dataset id `d_acde1106003906a75c3fa052592f2fcb`).
- Access: the official data.gov.sg [Download dataset API](https://guide.data.gov.sg/developer-guide/dataset-apis/download-dataset) (`initiate-download` then `poll-download`), with the legacy `datastore_search` API as an automatic fallback. Dataset metadata (`lastUpdatedAt`, coverage) comes from the [metadata API](https://guide.data.gov.sg/developer-guide/dataset-apis/get-dataset-metadata).
- Licence: [Singapore Open Data Licence v1.0](https://data.gov.sg/open-data-licence). Commercial use, redistribution and adaptation are permitted with attribution. If you republish the data, include a notice such as: *Contains information from "Government Procurement via GeBIZ" accessed on {date} from data.gov.sg, made available under the terms of the Singapore Open Data Licence version 1.0 (https://data.gov.sg/open-data-licence).* Do not present the output as official or endorsed by the Singapore Government.
- Personal data: the awards feed is organisational, but `supplierName` can be a sole proprietorship or partnership trading under an individual's name, and the tender description occasionally names an officer. Those values are published lawfully by the Ministry of Finance under the Singapore Open Data Licence, but where a value identifies an individual it is personal data under Singapore's Personal Data Protection Act 2012 (PDPA).
- Downstream use — direct marketing in particular, including the PDPA's Do Not Call rules — is the buyer's responsibility, not the publisher's. The Actor adds no contact details and no enrichment from other sources.

This Actor is independent and not affiliated with GeBIZ, the Ministry of Finance or data.gov.sg.

### Limits and freshness

- **Freshness:** MOF refreshes the dataset about once a year, shortly after the Singapore financial year ends on 31 March (data.gov.sg lists the collection's update frequency as *annual*). At the time of writing it covers award dates from 2021-04-01 to 2026-03-31 (FY2021 to FY2025) and was last updated on 2026-04-26. An award made today can therefore take up to a year to appear; this is not a real-time feed. The last refresh date is reported as `datasetLastUpdated` on every record and in `SUMMARY`. A run that specifies no dates automatically ends its window at the coverage end, so the default settings always return data; if you set `dateFrom`/`dateTo` explicitly and the window lies entirely after the coverage end, the run returns zero results and logs a warning naming that date.
- **Scope:** awarded tenders only (including "Awarded to No Suppliers" outcomes). Quotations, open tenders, tender documents, bidder lists and contact details are not in the dataset.
- **Fields:** exactly the seven columns MOF publishes, normalised (dates to ISO, amounts to numbers, whitespace trimmed). No enrichment is invented.
- **Volume:** the source is a single ~4.4 MB CSV that is downloaded once per run, so a run takes seconds regardless of filters. `maxItems` caps what is delivered and billed.
- **Rate limits:** data.gov.sg rate limits [reset every 10 seconds](https://guide.data.gov.sg/developer-guide/api-overview/api-rate-limits); without an API key you get 2 dataset-download calls and 4 datastore-search calls per 10 seconds (each endpoint has its own bucket). A run makes one `initiate-download` call, one `poll-download` call, one metadata call and one CSV fetch, and retries with back-off on HTTP 429, so several runs started back to back simply take a little longer. Schedule it weekly or monthly; more often is pointless given the annual refresh cadence.

### Use cases

- **Supplier and competitor intelligence:** list every contract a competitor has won, which agencies buy from them, and at what value; build target lists of agencies that buy what you sell.
- **Price benchmarking and bid strategy:** see historical awarded amounts for similar tenders (`keywords` + `agencies`) before pricing your next bid.
- **Lead generation and market sizing:** export suppliers winning work in a category (for example construction, IT services, training) to find partners, subcontractors or prospects; feed the JSON into a CRM or an LLM pipeline.

### Support

Found a problem or need another field or filter? Open an issue on the Actor's Issues tab on Apify Store. Issues are answered within 14 days.

# Actor input Schema

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

Case-insensitive words or phrases matched against the tender description (and tender number). A record matches if ANY keyword is found. Leave empty for all tenders.

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

Case-insensitive substrings matched against the awarding agency name, e.g. 'Housing and Development Board' or just 'Health'. Any match passes. Leave empty for all 110+ agencies.

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

Case-insensitive substrings matched against the winning supplier name, e.g. 'NCS' or 'Accenture'. Any match passes. Leave empty for all suppliers.

## `statuses` (type: `array`):

Case-insensitive match on tender\_detail\_status. Values in the dataset: 'Awarded to Suppliers', 'Awarded by Items', 'Award by interface record', 'Awarded to No Suppliers' (the last one has supplier 'Unknown' and amount 0). Leave empty to include all.

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

Earliest award date to include, YYYY-MM-DD (inclusive). The dataset starts at 2021-04-01 (FY2021). Overrides 'Days back'.

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

Latest award date to include, YYYY-MM-DD (inclusive). Defaults to today.

## `daysBack` (type: `integer`):

When 'Award date from' is empty, include awards from this many days before 'Award date to' (or today). The dataset is refreshed about once a year (after the 31 March financial year end), so the default is one year.

## `minAmount` (type: `number`):

Only return awards with awarded\_amt at or above this value in Singapore dollars. Amounts in the source can be fractional (e.g. 670374.5), so decimals are accepted. 0 keeps everything, including 'Awarded to No Suppliers' rows whose amount is 0.

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

Stop after this many results (newest award date first). You are charged per result returned. Defaults to 1000 when omitted; the Store form is prefilled with 100 for a cheap first run.

## Actor input object example

```json
{
  "keywords": [],
  "agencies": [],
  "suppliers": [],
  "statuses": [],
  "daysBack": 365,
  "minAmount": 0,
  "maxItems": 100
}
```

# Actor output Schema

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

All awards returned by the run, one JSON object each. Append ?format=csv or ?format=xlsx to download a spreadsheet.

## `summary` (type: `string`):

Counts, the date window used, source freshness and any per-source warnings, written at the end of the run.

# 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": [],
    "agencies": [],
    "suppliers": [],
    "statuses": [],
    "daysBack": 365,
    "minAmount": 0,
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("knotty_mistveil/singapore-gebiz-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": [],
    "agencies": [],
    "suppliers": [],
    "statuses": [],
    "daysBack": 365,
    "minAmount": 0,
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("knotty_mistveil/singapore-gebiz-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": [],
  "agencies": [],
  "suppliers": [],
  "statuses": [],
  "daysBack": 365,
  "minAmount": 0,
  "maxItems": 100
}' |
apify call knotty_mistveil/singapore-gebiz-tender-awards --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,knotty_mistveil/singapore-gebiz-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/GrcC3jSeroXiOitZd/builds/0Ll6YtYFjWhqqa9QR/openapi.json
