# Vietnam Tenders & Contract Awards (muasamcong) (`a-g-d/vn-tenders`) Actor

Tender notices and contract awards from Vietnam's national e-procurement portal (muasamcong.mpi.gov.vn) as English-keyed JSON: package, investor, VND prices, deadlines, provinces, winners and winning prices.

- **URL**: https://apify.com/a-g-d/vn-tenders.md
- **Developed by:** [Aloever Dulay](https://apify.com/a-g-d) (community)
- **Categories:** Lead generation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 tender notices

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

## Vietnam Tenders Actor (muasamcong.mpi.gov.vn)

Tender notices and contract awards from Vietnam's national e-procurement portal,
[muasamcong.mpi.gov.vn](https://muasamcong.mpi.gov.vn), as clean, English-keyed JSON.

- **Tender notices** (`recordType: "notices"`, the default): the notices published in a
  time window, filtered by keyword, procurement field and province, with the package,
  investor, selection method, budgeted price in VND, closing and opening times, locations
  and a link to each notice. Optionally, each notice also carries its details: procuring
  entity, project and plan, capital source, contract type and period, bid guarantee, lots
  and the names of the attached files.
- **Contract awards** (`recordType: "awards"`): the contractor-selection results
  published in a time window, with the outcome (awarded, no winner, cancelled, …), the
  winning contractors and their tax codes, the joint venture, the winning price next to
  the package price, and the result and approval dates. Optionally, each award also
  carries the published result: approval decision, contract type and period, every lot
  with its bidders and winner, cancellation details and document names. See
  [Contract awards](#contract-awards).

### Who needs this

- **Contractors and suppliers** bidding for Vietnamese public contracts who want new
  notices in their field and province every morning instead of searching the portal by
  hand.
- **Bid consultants and tender-alert services** building feeds or email digests.
- **Market-entry and trade teams** sizing public demand for works, goods or services by
  province.
- **Analysts, journalists and researchers** studying public procurement: who buys what,
  at what budget, under which procedure, and who wins at what price.
- **Sales and competitive-intelligence teams** tracking which companies win which
  contracts, how far below budget, and where.
- **AI agents and automations** that need a stable schema rather than a Vue front end and
  a Vietnamese-only UI.

### Input

| Field                | Type     | Default     | Description                                                                                                                                                                                                                              |
| -------------------- | -------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `recordType`         | string   | `"notices"` | `notices` for tender notices, `awards` for contract awards (published contractor-selection results). One run returns one record type.                                                                                                    |
| `keyword`            | string   | `""`        | Matched by the portal against the notice number (e.g. `IB2600537045`) and the package name, for notices and awards. Vietnamese text works best, e.g. `xây dựng`.                                                                         |
| `investField`        | string\[] | `[]` (all)  | `XL` works/construction, `HH` goods, `TV` consulting, `PTV` non-consulting services, `HON_HOP` mixed.                                                                                                                                    |
| `province`           | string   | `""` (all)  | Province code (e.g. `79`) or name in Vietnamese or English, with or without diacritics (`Ho Chi Minh`, `Đà Nẵng`, `Hai Phong City`). See [Province matching](#province-matching).                                                        |
| `openOnly`           | boolean  | `true`      | Notices only: keep notices whose bid closing time is still in the future. **Ignored for awards.**                                                                                                                                        |
| `publishedSince`     | string   | `24 hours`  | A relative span (`24 hours`, `3 days`, `2 weeks`, `90 minutes`), a date (`2026-09-20`, midnight Vietnam time) or an ISO-8601 timestamp. Notices filter on the notice's publication time, **awards on the result's** (`awardPublicDate`). |
| `maxItems`           | integer  | `100`       | Stop after this many notices or awards (1-10,000), newest first.                                                                                                                                                                         |
| `includeDetail`      | boolean  | `false`     | Also fetch each record's detail (one extra request per record, billed separately): notice details, or the published result for awards.                                                                                                   |
| `proxyConfiguration` | object   | no proxy    | Optional Apify Proxy. The portal sometimes resets connections from datacenter IPs; use a residential proxy if runs fail with connection errors.                                                                                          |

Every open notice: set `openOnly: true` and a long `publishedSince` such as `365 days`
(a notice's `publicDate` is its latest version, so amended notices count from the
amendment).

#### Province matching

Filtering happens on the portal by province code (`locations.provCode`). A numeric input
is used as the code. A name is folded (no diacritics, `đ` → `d`, no "Tỉnh", "Thành phố",
"Province" or "City") and matched against the portal's own province list, in Vietnamese
and English. Vietnam merged its provinces in July 2025; the portal lists the 34 current
provinces plus the 63 former ones, whose codes older notices still carry. A name matches
both, so `Ho Chi Minh` filters on `79` (current) and `701` (former). An unknown province
fails the run with the list of valid names.

### Output

One dataset item per tender notice (or per award, see [Contract awards](#contract-awards)),
newest publication first. Every item has a `recordType` field, `notice` or `award`; a run
stores one record type only, so a run's dataset is homogeneous. Keys are English, text
stays Vietnamese (UTF-8) exactly as published. Every timestamp from the portal is
ISO-8601 in Vietnam time (`+07:00`); `fetchedAt` is UTC. Codes are kept next to an English
`…Label` taken from the portal's own category lists; a code the actor does not know is
kept as is with a `null` label. The Output tab on this page documents every field of both
record types. The dataset has two table views: "Overview" for notices and "Awards" for awards.

A real item (notice IB2600537045, captured 2026-09-25) with `includeDetail: true`:

```json
{
  "recordType": "notice",
  "id": "80e7dea3-7faf-4353-9935-7dead7399dfd",
  "notifyNo": "IB2600537045",
  "version": "00",
  "bidName": "Chỉnh lý khối hồ sơ, tài liệu của Sở Y tế theo Đề án 2996/QĐ-UBND ngày 05/12/2025 của UBND tỉnh (nay là thành phố) Đồng Nai",
  "planNo": "PL2600235628",
  "investorName": "Sở Y tế Đồng Nai",
  "investorCode": "vn3600360747",
  "procuringEntityName": null,
  "procuringEntityCode": null,
  "investField": "PTV",
  "investFieldLabel": "Non-consulting",
  "bidForm": "DTRR",
  "bidFormLabel": "Open bidding",
  "bidMode": "1_MTHS",
  "bidModeLabel": "One stage one envelope",
  "processApply": "LDT",
  "processApplyLabel": "Law on Bidding/ Application of Law on Bidding",
  "bidPrice": 6383300000,
  "publicDate": "2026-09-25T18:44:43.020+07:00",
  "originalPublicDate": "2026-09-25T18:44:43.020+07:00",
  "bidCloseDate": "2026-10-04T09:00:00.000+07:00",
  "bidOpenDate": "2026-10-04T09:00:00.000+07:00",
  "status": "01",
  "statusLabel": "Posted",
  "statusForNotify": null,
  "isDomestic": true,
  "isInternet": true,
  "locations": [
    {
      "provinceCode": "75",
      "provinceName": "Thành phố Đồng Nai",
      "districtCode": null,
      "districtName": null
    }
  ],
  "detailUrl": "https://muasamcong.mpi.gov.vn/web/guest/contractor-selection?p_p_id=egpportalcontractorselectionv2_WAR_egpportalcontractorselectionv2&…&_egpportalcontractorselectionv2_WAR_egpportalcontractorselectionv2_notifyId=80e7dea3-7faf-4353-9935-7dead7399dfd&…",
  "sourceUrl": "https://muasamcong.mpi.gov.vn/o/egp-portal-contractor-selection-v2/services/smart/search?token=",
  "fetchedAt": "2026-09-25T20:47:16.000Z",
  "detail": {
    "sourceUrl": "https://muasamcong.mpi.gov.vn/o/egp-portal-contractor-selection-v2/services/expose/lcnt/bid-po-bido-notify-contractor-view/get-by-id?token=",
    "bidNo": "BP2600584295",
    "procuringEntityName": "Sở Y tế Đồng Nai",
    "procuringEntityCode": "vn3600360747",
    "projectName": "Thực hiện Đề án quản lý và xử lý nghiệp vụ đối với khối hồ sơ, tài liệu đã được thống kê trước khi sắp xếp tổ chức bộ máy của Sở Y tế thành phố Đồng Nai",
    "planName": "Thực hiện Đề án quản lý và xử lý nghiệp vụ đối với khối hồ sơ, tài liệu đã được thống kê trước khi sắp xếp tổ chức bộ máy của Sở Y tế thành phố Đồng Nai",
    "capitalSource": "Nguồn dự phòng ngân sách thành phố năm 2026",
    "contractType": "DGCD",
    "contractTypeLabel": "Fixed price",
    "contractPeriod": 60,
    "contractPeriodUnit": "day",
    "bidValidityPeriod": 90,
    "bidValidityPeriodUnit": "day",
    "guaranteeValue": 80000000,
    "guaranteeForm": "Thư bảo lãnh hoặc giấy chứng nhận bảo hiểm bảo lãnh",
    "feeFree": true,
    "feeValue": null,
    "bidPrice": 6383300000,
    "bidPriceCurrency": "VND",
    "bidStatus": "PUB_MT",
    "bidStatusLabel": "Bidding documents released",
    "bidOpenLocation": "https://muasamcong.mpi.gov.vn",
    "executionLocation": null,
    "isMultiLot": false,
    "lots": [],
    "approvalDecision": {
      "number": "887/QĐ-SYT",
      "date": "2026-09-25T18:44:00.000+07:00",
      "agency": "Sở Y tế Đồng Nai"
    },
    "files": [
      {
        "kind": "decision",
        "fileId": "853c37e6-cb77-49a4-9eeb-4326b25fc97a",
        "fileName": "IB2600537045_QuyetDinhPheDuyetHSMT_25_09_2026.pdf"
      }
    ]
  },
  "detailUnavailableReason": null
}
```

A multi-lot package (IB2600520498, 13 lots) lists its lots:

```json
{
  "isMultiLot": true,
  "lots": [
    {
      "lotNo": "PP2600368522",
      "lotName": "Phần (lô) 1: Vật tư dùng cho nội soi (yêu cầu tham gia trọn phần)",
      "lotPrice": 23532643000,
      "lotEstimatePrice": 23532643000,
      "guaranteeValue": null,
      "contractPeriod": 12,
      "contractPeriodUnit": "month"
    }
  ]
}
```

Without `includeDetail`, `detail` is `null` and `detailUnavailableReason` is
`not_requested`. With it, `detail` is `null` only when the reason says why:

| `detailUnavailableReason` | Meaning                                                                                                                            |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `no_data_from_portal`     | The portal has no public detail for this record. For notices: simplified online quotations (`bidForm` CGTTRG) while they are open. |
| `request_failed`          | The portal did not answer the detail request after retries. The record is still stored.                                            |
| `spending_limit`          | Your spending limit covered the record but not its detail.                                                                         |

Notice details come from the service the portal's own notice page uses for the notice:
notices under the procurement law (`processApply` LDT) from one, notices under KHAC, ADB
or WB rules from another (`detail.sourceUrl` says which). The second service has no
separate project name, so `projectName` holds the plan-level name it publishes (`pName`).

### Contract awards

Set `recordType` to `"awards"` to get published contractor-selection results (KQLCNT)
instead of notices. The actor reads the portal's own "result of bidder selection" search:
tender notices at the published-result step, filtered on the result's publication time.
Every other filter works as for notices except `openOnly`, which is ignored. Each award
comes from the search index alone (one request per page); `includeDetail` adds the full
published result (one request per award).

A real award (IB2600550046, a three-company joint venture, captured 2026-09-26) with
`includeDetail: true`:

```json
{
  "recordType": "award",
  "id": "4ef7f384-b814-49f8-896a-3095365a1983",
  "notifyNo": "IB2600550046",
  "version": "00",
  "bidName": "Gói thầu số 14: Toàn bộ phần xây lắp còn lại + Thiết bị PCCC, cấp điện",
  "planNo": "PL2600052522",
  "investorName": "Ban Quản lý dự án Đầu tư xây dựng khu vực 1",
  "investorCode": "vn3301747506",
  "procuringEntityName": null,
  "procuringEntityCode": null,
  "investField": "XL",
  "investFieldLabel": "Construction",
  "bidForm": "CDT",
  "bidFormLabel": "Direct contracting",
  "bidMode": "1_MTHS",
  "bidModeLabel": "One stage one envelope",
  "processApply": "LDT",
  "processApplyLabel": "Law on Bidding/ Application of Law on Bidding",
  "bidPrice": 49120167000,
  "publicDate": "2026-09-22T10:40:32.212+07:00",
  "originalPublicDate": "2026-09-22T10:40:32.212+07:00",
  "bidCloseDate": "2026-09-25T08:00:00.000+07:00",
  "bidOpenDate": "2026-09-25T08:10:00.000+07:00",
  "bidNo": null,
  "resultId": "98066988-f872-4d59-bf02-3d5e95763e3b",
  "awardPublicDate": "2026-09-26T10:48:28.000+07:00",
  "decisionDate": "2026-09-25T23:59:59.000+07:00",
  "outcome": "awarded",
  "outcomeCode": "CNTTT",
  "outcomeLabel": "There is successful bidder",
  "winnerNames": [
    "CÔNG TY CỒ PHẦN THƯƠNG MẠI VÀ XÂY DỰNG QUỐC TOÀN",
    "CÔNG TY TRÁCH NHIỆM HỮU HẠN MỘT THÀNH VIÊN RỒNG VIỆT",
    "CÔNG TY TNHH MỘT THÀNH VIÊN THIẾT KẾ XÂY DỰNG THANH AN"
  ],
  "winnerCodes": ["vn3300456215", "vn3301166981", "vn3301591908"],
  "jointVentureName": "Liên danh Trường THCS Phú Thanh",
  "winningPrices": [46661689000, 46661689000, 46661689000],
  "winningPrice": 46661689000,
  "resultPetitionCount": 0,
  "isDomestic": true,
  "isInternet": false,
  "locations": [
    {
      "provinceCode": "46",
      "provinceName": "Thành phố Huế",
      "districtCode": "32259",
      "districtName": "Phường Dương Nỗ"
    }
  ],
  "detailUrl": "https://muasamcong.mpi.gov.vn/web/guest/contractor-selection?p_p_id=egpportalcontractorselectionv2_WAR_egpportalcontractorselectionv2&…&_egpportalcontractorselectionv2_WAR_egpportalcontractorselectionv2_step=kqlcnt&_egpportalcontractorselectionv2_WAR_egpportalcontractorselectionv2_inputResultId=98066988-f872-4d59-bf02-3d5e95763e3b&…",
  "sourceUrl": "https://muasamcong.mpi.gov.vn/o/egp-portal-contractor-selection-v2/services/smart/search?token=",
  "fetchedAt": "2026-09-26T09:20:46.000Z",
  "detail": {
    "sourceUrl": "https://muasamcong.mpi.gov.vn/o/egp-portal-contractor-selection-v2/services/expose/contractor-input-result/get?token=",
    "bidNo": "BP2600236611",
    "resultStatus": "IS_PUBLISH",
    "procuringEntityName": "Ban Quản lý dự án Đầu tư xây dựng khu vực 1",
    "procuringEntityCode": "vn3301747506",
    "decision": {
      "number": "923/QĐ-BQLKV1",
      "date": "2026-09-25T23:59:59.000+07:00",
      "agency": "Ban Quản lý dự án đầu tư xây dựng khu vực 1"
    },
    "contractType": "DGDC",
    "contractTypeLabel": "Adjusted unit price",
    "contractPeriod": 360,
    "contractPeriodUnit": "day",
    "packagePrice": 48910711000,
    "estimatedPrice": 49120167000,
    "isMultiLot": false,
    "lots": [
      {
        "lotNo": "BP2600236611",
        "lotName": "Gói thầu số 14: Toàn bộ phần xây lắp còn lại + Thiết bị PCCC, cấp điện",
        "lotPrice": 48910711000,
        "contractors": [
          {
            "name": "CÔNG TY CỒ PHẦN THƯƠNG MẠI VÀ XÂY DỰNG QUỐC TOÀN",
            "code": "vn3300456215",
            "jointVentureName": "Liên danh Trường THCS Phú Thanh",
            "jointVentureCode": "PC2600030724",
            "won": true,
            "winningPrice": 46661689000,
            "notSelectedReason": null
          },
          {
            "name": "CÔNG TY TRÁCH NHIỆM HỮU HẠN MỘT THÀNH VIÊN RỒNG VIỆT",
            "code": "vn3301166981",
            "jointVentureName": "Liên danh Trường THCS Phú Thanh",
            "jointVentureCode": "PC2600030724",
            "won": true,
            "winningPrice": 46661689000,
            "notSelectedReason": null
          },
          {
            "name": "CÔNG TY TNHH MỘT THÀNH VIÊN THIẾT KẾ XÂY DỰNG THANH AN",
            "code": "vn3301591908",
            "jointVentureName": "Liên danh Trường THCS Phú Thanh",
            "jointVentureCode": "PC2600030724",
            "won": true,
            "winningPrice": 46661689000,
            "notSelectedReason": null
          }
        ]
      }
    ],
    "cancellation": null,
    "files": [
      {
        "kind": "decision",
        "fileId": "1b04a4dc-0914-43f1-89ab-0f6ac1d6ca37",
        "fileName": "11. QD PD CDT Tr Phu Thanh GT14.pdf"
      },
      {
        "kind": "evaluation_report",
        "fileId": "b74d343f-c982-45db-871b-ca72e35d51a5",
        "fileName": "7. BC xet thau Tr Phu Thanh2.pdf"
      },
      {
        "kind": "bid_opening_record",
        "fileId": "3e728573-0a27-47b0-9a8b-0ef1e8e4a893",
        "fileName": "8. BB mo thau Tr Phu Thanh2.pdf"
      }
    ]
  },
  "detailUnavailableReason": null
}
```

A multi-lot package lists every lot with its bidders; IB2600534396, an online quotation of
14 lots won by 11 companies, starts:

```json
{
  "isMultiLot": true,
  "lots": [
    {
      "lotNo": "PP2600394844",
      "lotName": "Bơm tiêm sử dụng 1 lần 5ml/cc, kim các cỡ",
      "lotPrice": 257200000,
      "contractors": [
        {
          "name": "CÔNG TY TNHH MỘT THÀNH VIÊN DƯỢC SÀI GÒN",
          "code": "vn0300523385",
          "jointVentureName": null,
          "jointVentureCode": null,
          "won": false,
          "winningPrice": null,
          "notSelectedReason": "Không đạt đánh giá về giá (xếp hạng 2)"
        },
        {
          "name": "CÔNG TY TNHH THIẾT BỊ & VẬT TƯ Y TẾ HOA NĂNG",
          "code": "vn0312636538",
          "jointVentureName": null,
          "jointVentureCode": null,
          "won": true,
          "winningPrice": 236000000,
          "notSelectedReason": null
        }
      ]
    }
  ]
}
```

How to read an award:

- **`outcome`** models every result status the portal publishes: `awarded` (CNTTT),
  `no_winner` (KCNTTT), `cancelled` (DHT, the bid was cancelled), `result_cancelled`
  (DHKQLCNT), `result_voided` (VHH), `result_not_recognised` (KCN), `suspended` (DC). Any
  other code becomes `other`, and the raw code is always in `outcomeCode`. Nothing is
  dropped: cancelled and failed tenders are awards too.
- **Winners.** `winnerNames` lists the members of a winning joint venture, or each distinct
  winner; online quotations (CGTTRG) and some competitive offers only publish the winner in
  another index field, which the actor falls back to. `winnerCodes` (vn + tax or business
  number) and `winningPrices` are **separate lists, passed through as the index publishes
  them and never padded or re-paired**: the index orders names and codes independently
  (IB2600534396 lists the same 11 companies in different orders), can omit a joint-venture
  member's code (3 names, 2 codes on IB2600529885), and lists one price per lot (14 prices
  for 11 companies on IB2600534396). For exact name, code and price per lot, use
  `includeDetail`: `detail.lots[].contractors[]` pairs them, and marks the winner of each
  lot with `won: true`.
- **`winningPrice`** is the total awarded: the sum of `winningPrices`, except that a joint
  venture of a single-lot package, which the index lists once per member with the same
  price, counts once (IB2600550046: 46.7 bn VND, not 140 bn). The portal's own list page
  adds the repeated prices up; the actor does not.
- **Order.** Awards come newest result first (`awardPublicDate`). The index can only sort
  by the notice's publication date, so the actor splits the time window until one page
  holds it and sorts each page: that costs extra search calls (7 search calls for the 20
  newest awards of a day in a live run on 2026-09-26), still a fraction of a detail call's traffic.

### Pricing

Pay per event. The events are:

| Event           | Charged for                                                                                                   |
| --------------- | ------------------------------------------------------------------------------------------------------------- |
| `tender-notice` | Each notice stored in the dataset (`recordType: "notices"`).                                                  |
| `tender-detail` | Each notice stored **with** its `detail` object (only with `includeDetail`; never for a `null` detail).       |
| `award-result`  | Each award stored in the dataset (`recordType: "awards"`), whatever its outcome.                              |
| `award-detail`  | Each award stored **with** its result `detail` object (only with `includeDetail`; never for a `null` detail). |

A run charges only the two events of its record type. Apify's standard run-start event
covers starting the actor. Items are stored first and charged after, so you never pay for
data you did not receive. When your spending limit runs out, the run stops cleanly: it
plans each page against the remaining limit, fetches details only for records it can
bill, and never stores an unpaid record or detail.

### Data source

- **Portal:** Vietnam's national e-procurement system (Hệ thống mạng đấu thầu quốc gia).
  The actor reads the same JSON services the portal's own pages use:
  `…/services/smart/search` for notices and awards,
  `…/services/expose/lcnt/bid-po-bido-notify-contractor-view/get-by-id` for notice details
  under the procurement law, `…/services/lcnt_tbmt_ttc_vk_adb` for KHAC, ADB and WB notice
  details, and `…/services/expose/contractor-input-result/get` for award results.
- **Legal basis:** Vietnamese procurement law requires these notices and results to be
  published.
  robots.txt allows everything (`Disallow:` empty) and no terms of use are linked from the
  portal. The actor
  outputs **metadata and links only**: it never downloads, mirrors or redistributes the
  bidding documents or attached files (the portal serves those only through its desktop
  signing agent anyway).
- **Politeness:** requests are sequential, detail requests are spaced by 300 ms, the
  User-Agent is `vn-tenders-actor/0.2 (+https://apify.com/a-g-d/vn-tenders)`,
  and responses are gzip-compressed. Search pages hold up to 50 records.
- **reCAPTCHA:** the browser attaches a reCAPTCHA v3 token as `?token=`. The server
  requires the parameter but accepts it empty, which is what the actor sends. If the
  portal starts refusing (HTTP 400/401/403, or empty `page: null` answers that persist
  after retries), the run fails with a message saying the portal may now require a
  verified token. The actor does not solve captchas.
- **Volume.** Notices (observed 2026-09-25): about 4,000 open tender notices; 365-439 new
  or amended notices per weekday that week, far fewer at weekends (223 in the 24 hours to
  2026-09-26 09:20 UTC, a Saturday morning in Vietnam). Awards (measured 2026-09-26 at
  09:20-09:50 UTC): 3,219 results published in the trailing 7 days, 307 and 258 in the
  trailing 24 hours at those two times; over 30 days the award search reaches the
  10,000-hit cap, which the actor slices. Of the results published in those 30 days, 238
  were not awards (mostly cancelled bids) and 428 came from notices outside the
  procurement law (KHAC, WB).
- **Traffic per request** (response bytes on the wire, live runs of 2026-09-26): a search
  page of 50 notices about 10 KB, of 50 awards about 20 KB; a notice detail about 23 KB
  under the procurement law and 2.6 KB for KHAC/ADB/WB notices; an award result about
  5 KB (up to 20 KB for large multi-lot results).

### Limitations

- **No detail for open simplified online quotations.** Notices with `bidForm` CGTTRG have
  no public detail while they are open (both notice services return nothing, and the
  portal's own page shows none); they keep `detail: null` with `no_data_from_portal`. Their
  awards do have results.
- **Winner lists from the search index are not paired.** `winnerNames`, `winnerCodes` and
  `winningPrices` are three lists as the index publishes them (see
  [Contract awards](#contract-awards)); use `includeDetail` for exact per-lot pairs.
- **One search window holds at most 10,000 hits.** The actor splits the publication
  window into smaller ones when a query reaches that cap, so long windows still return
  every record (up to `maxItems`, at most 10,000 per run). Award windows are also split to
  read them newest result first.
- **Text is Vietnamese.** Names, locations and free-text fields are published in
  Vietnamese only; the actor translates codes, not text.
- **No file downloads.** Attached files are listed by name and id; the portal offers no
  public link to them.
- **Notice `statusForNotify` is passed through raw.** On notices, values such as `DHTBMT`
  (notice cancelled) stay raw codes; on awards the same field becomes `outcome`.
- **Datacenter reachability varies.** The portal sometimes resets every connection from a
  datacenter IP for a stretch of time. The actor retries with exponential backoff and
  jitter (capped well inside the default 300 s run timeout); if it still cannot connect,
  run it with Apify Proxy.

# Changelog

This Actor's version history is a separate document: https://apify.com/a-g-d/vn-tenders/changelog.md

# Actor input Schema

## `recordType` (type: `string`):

Tender notices (the default) or contract awards: notices whose contractor-selection result (winner, winning price, or cancellation) has been published. For awards, "Published since" applies to the result's publication time and "Open notices only" is ignored. One run returns one record type.

## `keyword` (type: `string`):

Matched by the portal against the notice number (e.g. IB2600537045) and the package name, for notices and awards alike. Vietnamese text works best, e.g. "xây dựng" or "bệnh viện". Leave empty for all records.

## `investField` (type: `array`):

Only records in these fields. Leave empty for all fields.

## `province` (type: `string`):

Only records with a location in this province. Enter the portal province code (e.g. 79) or the name in Vietnamese or English, with or without diacritics (e.g. "Ho Chi Minh", "Đà Nẵng", "Hai Phong City"). Names match the current province and any pre-2025 province of the same name. Leave empty for the whole country.

## `openOnly` (type: `boolean`):

Notices only: keep notices whose bid closing time is still in the future. Ignored for awards.

## `publishedSince` (type: `string`):

Only records published (or amended) after this point: a relative span like "24 hours", "3 days" or "2 weeks", a date like "2026-09-20" (midnight Vietnam time) or an ISO-8601 timestamp. Notices filter on the notice's publication time, awards on the result's. To list every open notice, use a long span such as "365 days".

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

Stop after storing this many notices or awards (newest first).

## `includeDetail` (type: `boolean`):

Also fetch each record's detail, one extra request per record, billed as a separate event. Notices: procuring entity, project and plan, capital source, contract type and period, bid guarantee, lots, attached file names (not available for open simplified online quotations, CGTTRG). Awards: result decision, contract type and period, per-lot bidders and winners, cancellation, file names.

## `proxyConfiguration` (type: `object`):

Optional. The portal sometimes resets connections from datacenter IPs; if runs fail with connection errors, try Apify Proxy (residential).

## Actor input object example

```json
{
  "recordType": "notices",
  "keyword": "",
  "investField": [],
  "province": "",
  "openOnly": true,
  "publishedSince": "7 days",
  "maxItems": 20,
  "includeDetail": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `notices` (type: `string`):

Filled by runs with recordType "notices" (the default): one item per tender notice matching the input filters, newest publication first: notice number, package name, investor, procurement field, selection method, budgeted price in VND, publication/closing/opening times in Vietnam time (+07:00), locations and a link to the portal page. With includeDetail, each item also carries a nested `detail` object (procuring entity, project and plan, capital source, contract type and period, bid guarantee, lots, attached file names).

## `awards` (type: `string`):

Filled by runs with recordType "awards": one item per published contractor-selection result, newest result first: outcome, winners and their codes, joint venture, winning price in VND, result and approval dates, plus the notice summary. With includeDetail, each item also carries the result detail (decision, contract type and period, per-lot bidders and winners, cancellation, file names).

# 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 = {
    "publishedSince": "7 days",
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("a-g-d/vn-tenders").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 = {
    "publishedSince": "7 days",
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("a-g-d/vn-tenders").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 '{
  "publishedSince": "7 days",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call a-g-d/vn-tenders --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,a-g-d/vn-tenders"
        }
    }
}
```

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/IGJfROj8jDjcHVtCj/builds/ySEDusPiyo5V0SoEC/openapi.json
