# Ghana GHANEPS Tenders & Awarded Contracts (ghaneps.gov.gh) (`a-g-d/gh-ghaneps`) Actor

Current tenders and awarded contracts from Ghana's national e-procurement system (GHANEPS) as English-keyed JSON: tender ID, title, procuring entity, procedure, status, dates, supplier, award amount and currency, and links to the tender page and notice PDF.

- **URL**: https://apify.com/a-g-d/gh-ghaneps.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

## Ghana GHANEPS Tenders & Awarded Contracts (ghaneps.gov.gh)

Current tenders and awarded contracts from Ghana's national electronic procurement
system, [GHANEPS](https://www.ghaneps.gov.gh/epps/home.do), as clean, English-keyed JSON.

- **Tenders** (`recordType: "tenders"`, the default): tenders open for bids (or in any
  other status you choose), newest publication first, with the tender ID, title, short
  description, procuring entity, procedure, status, publication date, bid submission
  deadline and links to the tender page and its notice PDF.
- **Awarded contracts** (`recordType: "awards"`): the portal's Awarded Contracts list,
  newest award first, with the tender, procuring entity, supplier, award date and time,
  amount and currency, lot, and links to the tender page and notice PDF.

### Who needs this

- **Suppliers and contractors** bidding for Ghanaian public contracts who want every new
  tender in their field each morning instead of checking the portal by hand.
- **Tender-alert services and bid consultants** building feeds, e-mail digests or
  WhatsApp/Telegram alerts for clients in Ghana.
- **Market-entry and trade teams** sizing public demand for goods, works and services by
  agency and region.
- **Analysts, journalists and researchers** following public spending: who buys what,
  which suppliers win, and for how much.
- **Sales and competitive-intelligence teams** tracking which companies win which contracts.
- **AI agents and automations** that need a stable schema instead of the portal's HTML.

### Input

| Field                | Type    | Default     | Description                                                                                                                                                                             |
| -------------------- | ------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `recordType`         | string  | `"tenders"` | `tenders` or `awards`. One run returns one record type.                                                                                                                                 |
| `keyword`            | string  | `""`        | Tenders: the title contains this text (the portal refuses `<`, `>`, `&` and `%`). Awards: the title, supplier name or lot name contains it. Case-insensitive.                           |
| `procuringEntity`    | string  | `""`        | The procuring entity contains this text, e.g. `District Assembly`, `Ghana Health Service`, `Ministry of Finance`. Case-insensitive.                                                     |
| `tenderStatus`       | string  | `"open"`    | **Tenders only**: `open` (accepting bids), `awaitingOpening`, `evaluation`, `awarded`, `cancelled`, `established`, `forArchival`, `archived`, or `all` for every tender listed.         |
| `category`           | string  | all         | **Tenders only**: `goods`, `works`, `technicalServices`, `consultingServices` or `disposals`.                                                                                           |
| `procedure`          | string  | all         | **Tenders only**: the procedure code, e.g. `nct` (National Competitive Tendering), `ict`, `rfq`, `sst`, `sss`, `qcbs.eoi`, `qcbs.rfp`, `lcs.eoi`, `ic`, `em`. The input form lists all. |
| `publishedSince`     | string  | `""`        | **Tenders only**: published at or after this point. A relative span (`24 hours`, `7 days`, `2 weeks`), a date (`2026-09-20`, midnight Ghana time) or an ISO-8601 timestamp.             |
| `awardedSince`       | string  | `""`        | **Awards only**: awarded at or after this point. Same formats as `publishedSince`.                                                                                                      |
| `maxItems`           | integer | `100`       | Stop after this many tenders or awards (1-20,000), newest first.                                                                                                                        |
| `proxyConfiguration` | object  | no proxy    | Optional Apify Proxy. Not needed normally; use it only if runs fail with connection errors.                                                                                             |

A filter that does not apply to the chosen record type is ignored, and the run log says
so. Ghana keeps GMT all year, so Ghana time is UTC. Examples:

```json
{ "category": "works", "procuringEntity": "District Assembly", "publishedSince": "14 days" }
```

```json
{ "recordType": "awards", "awardedSince": "7 days", "maxItems": 500 }
```

### Output

One dataset item per tender or per awarded contract. Every item has a `recordType` field,
`tender` or `award`; a run stores one record type only, so a run's dataset is
homogeneous. Keys are English; text is kept as the portal publishes it, trimmed and with
HTML entities decoded. Dates are ISO-8601 with an explicit `+00:00` (Ghana time is UTC),
`awardedOn` is a calendar day (`YYYY-MM-DD`), and `fetchedAt` is UTC. The Output tab on
this page documents every field. The dataset has two table views: "Tenders" and "Awards".

A real tender (captured 2026-09-26):

```json
{
  "recordType": "tender",
  "tenderId": "3641969",
  "title": "Supply of air conditioners (Nationwideationwide)",
  "procuringEntity": "JUDICIAL SERVICE",
  "description": "Supply of 147 Air Conditioners",
  "procedure": "National Competitive Tendering",
  "procedureCode": "nct",
  "category": null,
  "status": "Bid Submission",
  "publishedAt": "2026-09-25T15:48:07+00:00",
  "deadlineAt": "2026-10-14T14:00:00+00:00",
  "noticePdfUrl": "https://www.ghaneps.gov.gh/epps/cft/downloadNoticeForAdvSearch.do?resourceId=3641969",
  "detailUrl": "https://www.ghaneps.gov.gh/epps/cft/prepareViewCfTWS.do?resourceId=3641969",
  "sourceUrl": "https://www.ghaneps.gov.gh/epps/viewCFTSAction.do",
  "fetchedAt": "2026-09-26T14:52:00.064Z"
}
```

A real awarded contract (captured 2026-09-26):

```json
{
  "recordType": "award",
  "tenderId": "3273335",
  "title": "Procurement of Electronic Awards (Tablet, Laptop, Fridge and TV) for Civil Service Week Celebration 2026",
  "procuringEntity": "Office of the Head of Civil Service",
  "supplierName": "TRADE MART LIMITED",
  "awardedAt": "2026-09-24T13:11:15+00:00",
  "awardedOn": "2026-09-24",
  "amount": 1698945.72,
  "currency": "GHS",
  "amountText": "1698945.72 (GHS)",
  "lot": null,
  "noticePdfUrl": "https://www.ghaneps.gov.gh/epps/cft/downloadNotice.do?resourceId=3273335&lang=en&documentId=3633514&noticeType=430",
  "detailUrl": "https://www.ghaneps.gov.gh/epps/cft/prepareViewCfTWS.do?resourceId=3273335",
  "sourceUrl": "https://www.ghaneps.gov.gh/epps/viewAllAwardedContracts.do",
  "fetchedAt": "2026-09-26T14:52:17.089Z"
}
```

#### About IDs, lots and amounts

- `tenderId` is GHANEPS's own numeric ID for the tender, the same in the tender list, the
  award list and the portal's links, so tenders and their awards join on it. The procuring
  entity's reference number is on the tender page (`detailUrl`).
- A tender split into lots, or awarded to several suppliers, has one award per lot and
  supplier. The portal occasionally lists the very same award twice; the actor stores it
  once.
- `amount` is a number in `currency` (usually `GHS`, the Ghana cedi); `amountText` keeps
  the cell as printed. Single lines of framework or multi-lot awards often have no amount
  (the portal prints `N/A`), and then all three are `null`.
- `category` is filled only when you filter by `category`: the tender list does not print
  it (the tender page does).

### Pricing

Pay per event, charged only for records actually stored in your dataset:

- **`tender-notice`**: one per tender stored.
- **`award-result`**: one per awarded contract stored.

A run charges one of the two, depending on `recordType`; the actor defines no start event
of its own. It stores each page before it is charged and stops cleanly when your spending
limit is reached, so you never pay for data you cannot see.

### Data source and politeness

The data comes from the public, login-free pages of GHANEPS, run by Ghana's Public
Procurement Authority (PPA): the tender search behind "Search the tender registry" and
the "Awarded Contracts" list. The portal is slow (2-5 seconds per page) and serves 10
records per page, so the actor is deliberately gentle:

- **one request at a time, with at least 2 seconds between requests**, and an honest
  User-Agent that names the actor;
- retries connection resets, timeouts and server errors with exponential backoff inside a
  fixed budget, and stops with a clear error if the portal keeps refusing;
- stops shortly before the run's timeout and keeps what it has stored;
- never logs in, never downloads notice PDFs or tender documents (it links them).

Expect roughly 100 records a minute. The default 300-second run timeout covers the default
100 records comfortably; raise it for runs of several thousand.

**Deep history:** the PPA also publishes its procurement data in the Open Contracting Data
Standard (OCDS), monthly and months behind (listed as "Ghana: Public Procurement Authority"
in the Open Contracting Data Registry). Use that for multi-year analysis; use this actor
for what was published or awarded today.

### Data and privacy

The output is procurement metadata exactly as the government publishes it. Suppliers are
mostly companies, but some "ENTERPRISE" or "VENTURES" names are sole proprietorships named
after their owner, so `supplierName` can include a person's name: the actor keeps it as
published and adds nothing to it. It does not enrich, profile or combine records with
other sources, and it drops any e-mail address or phone number that appears in the text
it stores. If you process names of individuals, you are responsible for doing so lawfully.

### Limitations

- **Open tenders are few**: GHANEPS lists only the tenders run on it, about 60 open for
  bids at a time in September 2026. `tenderStatus: "all"` returns every tender the portal
  lists (about 4,000), in every status.
- **No reference number, category or UNSPSC code in the lists**: they are on each tender
  page (`detailUrl`), which the actor does not fetch.
- **Keyword and entity for tenders** are applied by the portal and re-checked by the actor
  ("contains"). The award list takes no filters, so for awards the actor reads the newest
  awards and keeps the matches, reading at most 5,000 of them per run; add `awardedSince`
  to bound a search by date.
- **Award amounts** can be `null` (see above); other currencies than GHS are parsed when
  the portal prints them with their code.
- The lists are read newest first while the portal keeps publishing; a record that moves
  between pages during a run is stored once.

# Changelog

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

# Actor input Schema

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

Tenders (the default): tenders from the GHANEPS tender search, newest publication first, by default those open for bids. Awarded contracts: the Awarded Contracts list, newest award first. One run returns one record type.

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

Tenders: the title contains this text (the portal refuses <, >, & and %). Awards: the title, supplier name or lot name contains it. Case-insensitive; leave empty for all records.

## `procuringEntity` (type: `string`):

Only records whose procuring entity contains this text, e.g. "Ghana Health Service", "District Assembly" or "Ministry of Finance". Case-insensitive; leave empty for all.

## `tenderStatus` (type: `string`):

Tenders only: open for bids (the default, the portal status Bid Submission), another status, or every tender the portal lists. Ignored for awards.

## `category` (type: `string`):

Tenders only: the procurement type. Leave empty for all. Ignored for awards (the award list does not show it).

## `procedure` (type: `string`):

Tenders only: the procurement procedure. Leave empty for all. Ignored for awards (the award list does not show it).

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

Tenders only: keep tenders published at or after this point. A relative span like "24 hours" or "7 days", a date like "2026-09-20" (midnight Ghana time, which is UTC) or an ISO-8601 timestamp. Leave empty for no lower bound.

## `awardedSince` (type: `string`):

Awards only: keep contracts awarded at or after this point. Same formats as Published since. Leave empty for no lower bound.

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

Stop after storing this many tenders or awards (newest first). The portal serves 10 records per page, about 80-100 records a minute; raise the run timeout for large runs.

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

Optional. The actor talks to ghaneps.gov.gh directly; use Apify Proxy only if runs fail with connection errors.

## Actor input object example

```json
{
  "recordType": "tenders",
  "keyword": "",
  "procuringEntity": "",
  "tenderStatus": "open",
  "publishedSince": "",
  "awardedSince": "",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `tenders` (type: `string`):

Filled by runs with recordType "tenders" (the default): one item per tender matching the input filters (by default those open for bids), newest publication first: tender ID, title, description, procuring entity, procedure (label and code), status, publication date and bid submission deadline (+00:00), and links to the tender page and notice PDF.

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

Filled by runs with recordType "awards": one item per awarded contract (tender, lot and supplier), newest award first: tender ID, title, procuring entity, supplier, award date and time (+00:00), amount with currency and as published, lot, and links to the tender page and notice PDF.

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

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

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

```

## MCP server setup

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

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/BFhxDHNM03jzfvoyG/builds/aSRE5xtdbafF27oUC/openapi.json
