# Global Tenders Radar — Etimad, World Bank & UN (`gulfdata/global-tenders-radar`) Actor

All tender portals in one run: Saudi Etimad, World Bank (100+ countries) and UN agencies (UNGM) — one unified schema, monitor mode across all sources, resilient partial-results design.

- **URL**: https://apify.com/gulfdata/global-tenders-radar.md
- **Developed by:** [Ali Alshamrani](https://apify.com/gulfdata) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $7.00 / 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?

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

## Global Tenders Radar — Saudi Etimad, World Bank & UN (UNGM) in One Run

**All tender portals in one run.** Monitor Saudi government tenders (Etimad), World Bank procurement notices (100+ countries) and UN agency opportunities (UNGM) — merged into **one unified schema**, deduplicated across runs, sorted newest-first.

Stop juggling three subscriptions and three different data shapes. One scheduled run answers the only question that matters: *"what's new for me across the whole world today?"*

### Why this Actor

- 🌐 **Three major procurement ecosystems, one feed**: Saudi Arabia's Etimad, the World Bank's 100+ country programs, and 30+ UN agencies via UNGM.
- 🧬 **One unified schema** — `title`, `agency`, `country`, `tender_type`, `submission_deadline`, `published_date`, `source_url`... identical field names across all sources; `source` tells you where each record came from.
- 🔁 **Monitor mode across all sources**: previously seen tenders are remembered per source; you only pay for what's new.
- 🛡️ **Resilient by design**: if one portal is down, the others still deliver — partial results with the failure recorded in a run summary, never a dead run.
- 📇 **World Bank contact data included** (name, email, organization) — direct lead-gen value.
- 🤖 **AI-agent / MCP ready**: one consistent JSON contract for LLM pipelines, CRMs, Sheets, or Slack alerts.

### Use cases

- **Bid-intelligence teams**: one daily feed across every market you cover.
- **Multi-market consultancies & contractors**: Saudi + development-bank + UN opportunities without three scrapers.
- **AI agents**: a single tool call answering "what new tenders match X anywhere?"

### Input

| Field | Type | Description |
|---|---|---|
| `sources` | array | Which portals to scan: `etimad`, `worldbank`, `ungm` (default: all) |
| `keywords` | string | Passed to each source's own search where supported, title-matched otherwise |
| `country` | string | Country filter on the unified `country` field |
| `noticeType` | string | Type filter, e.g. "bid", "proposal" |
| `sinceDays` | integer | Only tenders published in the last N days (default 7) |
| `maxRecordsPerSource` | integer | Fetch cap per source per run (default 200) |
| `monitorMode` | boolean | Push only NEW tenders (default true) |
| `useResidentialProxy` | boolean | Used only for the Etimad source, which blocks datacenter IPs (default true) |

### Output

Unified records, newest first. Example (one from each source):

```json
{ "tender_id": "1096164", "title": "مستلزمات نظافة", "source": "etimad",
  "agency": "مستشفى شرورة", "country": "Saudi Arabia", "tender_type": "شراء مباشر",
  "published_date": "2026-08-28", "submission_deadline": "2026-09-08T09:59:00",
  "source_url": "https://tenders.etimad.sa/Tender/DetailsForVisitor?STenderId=..." }
```

```json
{ "tender_id": "OP00377540", "title": "Construction of additional classrooms...", "source": "worldbank",
  "agency": "Assam PWD", "country": "India", "tender_type": "Invitation for Bids",
  "published_date": "2026-08-26", "contact_email": "...", 
  "source_url": "https://projects.worldbank.org/en/projects-operations/procurement-detail/OP00377540" }
```

```json
{ "tender_id": "312633", "title": "ITB 095.2026 Construcción de cerramientos", "source": "ungm",
  "agency": "FAO", "country": "Bolivia", "tender_type": "Invitation to bid",
  "published_date": "2026-08-28", "submission_deadline": "2026-09-15T03:00:00Z",
  "source_url": "https://www.ungm.org/Public/Notice/312633" }
```

Each run also writes a per-source summary (fetched / new / errors) to the named key-value store `radar-seen-tenders` under `__radar_summary`.

### Scheduling

One scheduled run per day, `monitorMode: true`, connected to a Slack/email/Sheets integration — a morning briefing of every new opportunity across all portals.

### Prefer a single source?

Each portal is also available as a focused standalone Actor with source-specific extras:

- [Etimad Saudi Tenders Monitor](https://apify.com/gulfdata/etimad-tenders-monitor) — Hijri dates, booklet fees, activity filters
- [World Bank Tenders Monitor](https://apify.com/gulfdata/worldbank-tenders-monitor) — project metadata, full notice text
- [UNGM Tenders Monitor](https://apify.com/gulfdata/ungm-tenders-monitor) — UN-agency filters

### Fair use & disclaimer

This Actor reads publicly available procurement notices from each portal at the same polite request rates as our standalone actors (site-default page sizes, paced requests). It is not affiliated with, or endorsed by, Etimad, the World Bank Group, UNGM or any UN agency. You are responsible for complying with each source's terms and applicable regulations.

# Actor input Schema

## `sources` (type: `array`):

Which tender portals to scan. Default: all of them.

## `keywords` (type: `string`):

Optional keywords. Passed to each source's own search where supported (Etimad, UNGM) and matched against titles otherwise.

## `country` (type: `string`):

Optional country name filter, e.g. 'Kenya' or 'Saudi Arabia' (substring match on the unified `country` field).

## `noticeType` (type: `string`):

Optional type filter matched against each source's tender type, e.g. 'bid', 'proposal'.

## `sinceDays` (type: `integer`):

Ignore tenders published earlier than this many days ago.

## `maxRecordsPerSource` (type: `integer`):

Upper bound of records fetched from EACH source per run.

## `monitorMode` (type: `boolean`):

Previously seen tenders (per source) are remembered across runs and only new ones are pushed. Ideal for scheduled daily runs.

## `useResidentialProxy` (type: `boolean`):

Only the Etimad source needs it (the portal blocks datacenter IPs); World Bank and UNGM are always fetched directly.

## Actor input object example

```json
{
  "sources": [
    "etimad",
    "worldbank",
    "ungm"
  ],
  "sinceDays": 7,
  "maxRecordsPerSource": 200,
  "monitorMode": true,
  "useResidentialProxy": true
}
```

# Actor output Schema

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

Unified tender records from all enabled sources, newest first (JSON items 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("gulfdata/global-tenders-radar").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("gulfdata/global-tenders-radar").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 '{}' |
apify call gulfdata/global-tenders-radar --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,gulfdata/global-tenders-radar"
        }
    }
}

```

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/0OZUR5UKGJBFn49bl/builds/Xm6DoIW8FyrUkfZV9/openapi.json
