# Jamaica GOJEP Contract Award Scraper (`publicmoney/jamaica-gojep-scraper`) Actor

Extract Jamaican contract award notices from the Government of Jamaica Electronic Procurement system: procurement method, procuring entity, notice title, contract amount, publication date. Export data, run via API, schedule and monitor runs, or integrate with other tools.

- **URL**: https://apify.com/publicmoney/jamaica-gojep-scraper.md
- **Developed by:** [Public Money](https://apify.com/publicmoney) (Apify)
- **Categories:** Business
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.00 / 1,000 tenders

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

This Actor reads Jamaican contract award notices from the Government of Jamaica Electronic Procurement system. It returns one record per contract, filtered server-side by keyword so a run returns what you asked for rather than everything. The portal itself is built for someone reading one contract at a time, which is what makes a pipeline over it painful. Each record comes back with a stable set of named fields, so the shape does not change between runs.

### What it does

- Returns **one record per contract**, with `title` as the first column.
- **Filters at the source, not after it.** The keyword is passed to the portal, so a narrow query costs less rather than the same.
- Handles the pagination. The portal serves contracts a page at a time and the Actor walks them until your **Max items** cap is reached.
- Normalises the source into named fields, so `procuringEntity` means the same thing on every run.
- Needs **no API key**. The source is open data and the Actor reads it unauthenticated.
- Reads `www.gojep.gov.jm` directly rather than scraping a rendered page, so a layout change on the site does not break the run.

### Use cases

| You need to | How this Actor does it |
| --- | --- |
| See who is winning work | Group by the supplier column and total the values |
| Benchmark a price | Filter by keyword and compare award values across buyers |
| Track a competitor | Filter on their name and watch what they are awarded |
| Feed a research agent | Call the Actor over MCP and let the model set the filters |
| Build a history | Schedule the run and let the dataset accumulate |

### Quick start

1. Click **Try for free**.
2. Put a **Keyword** in, or leave it empty to take everything the filters allow.
3. Set **Max items**, which is what caps the cost of the run.
4. Click **Start**, then export as JSON, CSV, Excel or XML, or read the dataset over the API.

### Input

| Field | Type | Default | What it controls |
| --- | --- | --- | --- |
| `maxPages` | integer | `5` | Caps how deep the pagination goes |
| `keyword` | string | empty | Matched server-side by the portal, so a narrow keyword cuts the run and the bill rather than filtering after the fact |
| `procurementMethod` | string | empty | Client-side filter on the procurement method, for example Restricted Bidding (RB), Open Bidding |
| `maxItems` | integer | `500` | Caps how many records are returned, and therefore what the run costs |

```json
{
    "keyword": "bridge",
    "maxItems": 500
}
```

### Output

One dataset item per contract, with the same named fields on every run.

| Field group | Fields |
| --- | --- |
| Dates | `publishedDate`, `tenderUrl` |
| Money | `contractAmount` |
| Parties | `procuringEntity` |
| Detail | `title`, `procurementMethod` |

```json
{
    "title": "Replacement of the north bridge deck",
    "procuringEntity": "Department of Transportation",
    "contractAmount": 184220.5,
    "publishedDate": "2026-09-04",
    "tenderUrl": "https://example.gov/notice/8842"
}
```

### Integrations

Run it over the API and get the rows back in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/publicmoney~jamaica-gojep-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keyword": "bridge", "maxItems": 500}'
```

From Python:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("publicmoney/jamaica-gojep-scraper").call(run_input={"keyword": "bridge", "maxItems": 500})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

Give an AI agent the Actor over MCP:

```json
{
    "mcpServers": {
        "apify": {
            "url": "https://mcp.apify.com/?actors=publicmoney/jamaica-gojep-scraper"
        }
    }
}
```

Schedules run it on any cron, webhooks fire when a run finishes, and platform integrations push the
dataset to Google Sheets, Slack, Airtable, Zapier or your own endpoint.

### Cost

Pay per event, so you pay for records rather than compute time.

| Event | Free tier | Top volume tier |
| --- | --- | --- |
| Tender | $0.002 | $0.0007 |
| Actor start | $0.00005 per GB | Same |

Six volume tiers apply, so the per-record price falls with monthly volume. The filters are the lever on cost: a keyword and a date range are applied by the portal before anything is returned, so a narrow run is a cheap run. **Max items** is the hard cap.

### Troubleshooting

| Issue | Solution |
| --- | --- |
| The run returns nothing | The filters excluded everything. Widen the date range or clear the keyword, and remember the keyword is matched by the portal rather than by us, so it matches the portal's way. |
| Fewer records than the portal shows | **Max items** caps the run. Raise it, and check the date range covers the period you meant. |
| The run is slower than expected | The portal serves contracts a page at a time and the Actor walks the pages. A narrower filter is faster as well as cheaper. |
| A field is empty on some contracts | The source publishes it for some records and not others. The field is dropped rather than filled with a placeholder, so an empty one means the portal had nothing. |
| The source changed and the run broke | Open an issue on the Issues tab. A daily test runs every Actor in this fleet against its live source, so a break is usually already known. |

### FAQ

#### Does this source have an API?

Some of these portals publish one and some do not, and where one exists it is usually paginated, rate limited and shaped differently from every other portal. This Actor gives you the same input and the same record shape as the rest of the fleet, so a pipeline over many jurisdictions does not need a special case for each.

#### Do I need an API key?

No. The source is open data and the Actor reads it unauthenticated. You need an Apify token to call the Actor over the API.

#### How do I keep the cost down?

Filter. The keyword, date range and amount are applied by the portal before any record is returned, so they cut the bill rather than just the output. **Max items** is the hard cap if you want a guaranteed ceiling, and a contract that returns no data is not charged.

#### Can I get history, or only what is current?

As far back as the portal publishes, using the date range. Portals differ: some carry years, some only an open window. To build your own history, schedule the Actor and let the dataset accumulate.

#### Can an AI agent call this Actor?

Yes. Add it to an MCP client with the config above and the model can set the filters itself. Every record is flat JSON, so no post-processing is needed.

#### Can I get the data into Excel or Google Sheets?

Yes. Export the dataset as XLSX or CSV, or connect the Google Sheets integration so each run appends to a sheet.

#### Is it legal to use this data?

This is public procurement and public spending data that governments publish deliberately, and the Actor reads it as published with no login. Named individuals do appear in some sources, such as a contact on a notice, so handle those under your own obligations. Take your own legal advice for your use case.

### Changelog

- **0.0.1** First release.

### Feedback

Found a column the portal publishes that this Actor misses, or a filter that does not behave the way the portal documents it? Open an issue on the Issues tab with the input you used and what you expected. A daily test runs every Actor in this fleet against its live source, so parser fixes ship fast.

# Actor input Schema

## `maxPages` (type: `integer`):

Result pages to walk. Each page holds about 10 records. Examples: 1, 5, 20. Default is 5.

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

Client-side filter on notice title and procuring entity. Examples: 'Emancipendence', 'Summer'.

## `procurementMethod` (type: `string`):

Client-side filter on the procurement method, for example Restricted Bidding (RB), Open Bidding.

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

Maximum number of records to return. 0 returns everything matched. Examples: 1, 500, 2000. Default is 500.

## Actor input object example

```json
{
  "maxPages": 5,
  "maxItems": 500
}
```

# Actor output Schema

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

Contracts matched by the run, one item per record, in the default dataset.

# 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 = {
    "maxPages": 5,
    "maxItems": 500
};

// Run the Actor and wait for it to finish
const run = await client.actor("publicmoney/jamaica-gojep-scraper").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 = {
    "maxPages": 5,
    "maxItems": 500,
}

# Run the Actor and wait for it to finish
run = client.actor("publicmoney/jamaica-gojep-scraper").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 '{
  "maxPages": 5,
  "maxItems": 500
}' |
apify call publicmoney/jamaica-gojep-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,publicmoney/jamaica-gojep-scraper"
        }
    }
}

```

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/flBxSbf7F2yWeM1DL/builds/LKzM6DmEoCeNt5Qms/openapi.json
