# Portugal Public Contracts (Portal BASE) (`joaopinto/contratos-publicos-pt`) Actor

Search every public contract signed in Portugal (contratos públicos, Portal BASE) by keyword, buyer, supplier, NIF, CPV code, price or date. Clean structured data, a daily new-contracts mode, and names of private individuals removed.

- **URL**: https://apify.com/joaopinto/contratos-publicos-pt.md
- **Developed by:** [João Pinto](https://apify.com/joaopinto) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 88.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 contracts

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

## Portugal Public Contracts (Portal BASE)

Search every public contract signed in Portugal and get clean, structured data: who bought what, from whom, for how much, and through which procedure.

The data covers all contracts that Portuguese public entities report to [Portal BASE](https://www.base.gov.pt) under the Public Contracts Code (Código dos Contratos Públicos). That's about 20–25 thousand new contracts a month.

*Em português: ver mais abaixo.*

### What you can do with it

- **Competitive intelligence:** see which contracts your competitors win, at what prices, and from which buyers.
- **Find buyers:** which municipalities, hospitals or universities buy what you sell, and how often.
- **Journalism and research:** follow how a public body spends money, or find repeated direct awards to the same supplier.
- **Daily monitoring:** schedule the actor with **Só contratos novos** (`onlyNew`) to get only the contracts published since the last run.
- **AI agents:** the output has fixed English field names and typed values, so you can use it directly in an LLM pipeline.

### Input

All filters are optional, and any filters you set must all match. The input form shows the field titles in Portuguese; the API name of each field is in brackets.

| Field | Example | Notes |
|---|---|---|
| Palavras-chave (`keywords`) | `software licenças` | Every word must appear in the contract description. Not case or accent sensitive. |
| Entidade adjudicante (`contractingEntity`) | `Reforma Tecnológica` or `508184509` | Part of the buyer's name, or its 9-digit NIF (tax number) |
| Adjudicatário (`contractor`) | `Claranet` or `510728189` | Part of the supplier's name, or its NIF |
| Códigos CPV (`cpvPrefixes`) | `48`, `72` | CPV code prefixes: `48` = software, `72` = IT services |
| Tipos de procedimento (`procedureTypes`) | `Concurso público` | For example `Ajuste direto` (direct award) or `Consulta prévia` |
| Publicado desde / até (`dateFrom`, `dateTo`) | `2026-01-01` | Publication date on BASE. By default, the last 30 days. |
| Preço mínimo / máximo (`minPrice`, `maxPrice`) | `10000` | Contract price in euros |
| Só contratos novos (`onlyNew`) | `true` | Returns only contracts not returned by a previous run with the same filters |
| Máximo de contratos (`maxItems`) | `1000` | Upper limit per run |

Example, IT contracts over €50,000 awarded by Lisbon entities this year:

```json
{
  "contractingEntity": "Lisboa",
  "cpvPrefixes": ["48", "72"],
  "minPrice": 50000,
  "dateFrom": "2026-01-01"
}
```

### Output

One item per contract. You can export it to JSON, CSV or Excel.

```json
{
  "id": "12014814",
  "url": "https://www.base.gov.pt/Base4/pt/detalhe/?type=contratos&id=12014814",
  "description": "Aquisição de serviços para obtenção de Selo de Usabilidade e Acessibilidade Digital Ouro na Página/Portal/App SASocial",
  "contractTypes": ["Aquisição de serviços"],
  "procedureType": "Ajuste Direto Regime Geral",
  "contractingEntities": [{ "nif": "600052737", "name": "Serviços de Ação Social do Instituto Politécnico de Coimbra", "isSme": null, "isLikelyPerson": false }],
  "contractors": [{ "nif": "515615021", "name": "XpertGo - Business Solutions Development, Lda", "isSme": true, "isLikelyPerson": false }],
  "bidders": [],
  "priceEur": 9000.0,
  "basePriceEur": 9000.0,
  "effectivePriceEur": null,
  "publicationDate": "2025-12-04",
  "signingDate": "2026-02-23",
  "awardDecisionDate": "2025-11-13",
  "closeDate": null,
  "executionDays": 81,
  "executionPlaces": [{ "country": "Portugal", "district": "Coimbra", "municipality": "Coimbra" }],
  "nuts": [],
  "cpv": [{ "code": "72210000-0", "description": "Serviços de programação de pacotes de software" }],
  "frameworkAgreement": null,
  "announcementNumber": null,
  "legalBasis": "Artigo 20.º, n.º 1, alínea d) do Código dos Contratos Públicos",
  "awardCriteriaTypes": ["Monofator"],
  "isGreen": false,
  "isCentralized": false,
  "lots": [],
  "procedureDocumentsUrl": null
}
```

- Dates use the ISO format (`YYYY-MM-DD`) and prices are numbers in euros.
- Missing values are always `null` or `[]`, never empty strings.
- `bidders` lists the companies that took part in the procedure, when the source includes them (about 40% of contracts).

### Data source and freshness

The actor reads the **open data that IMPIC publishes weekly** on [dados.gov.pt](https://dados.gov.pt/datasets/contratos-publicos-portal-base-impic-contratos-de-2012-a-2026). It does not scrape the BASE website. This makes it reliable, and polite to the public servers.

As a result, **the newest contracts arrive with a delay of up to about a week**. That delay comes from the source. For contracts that are already signed, it rarely matters.

This actor is not affiliated with IMPIC or Portal BASE.

### Privacy

Some contractors are private individuals, such as doctors, lawyers or trainers hired directly. The source already hides their NIF but still includes their name.

This actor goes further: when a contractor or bidder looks like a private individual, the actor **removes the name** and sets `isLikelyPerson: true`. The check uses the NIF prefix, or the absence of a legal form (Lda, S.A., etc.) in the name.

### Pricing

You pay per contract returned (see the **Pricing** tab). Use **Máximo de contratos** (`maxItems`) to cap the cost of each run.

A typical run takes about 4–5 minutes. It reads three yearly files, because many contracts are published months or years after they are signed.

### Limitations

- Contracts only. Open tenders (anúncios) are not included yet.
- Search works on the contract description, which is the text the public entity wrote. Search for the words they would use, in Portuguese.
- About 0.7% of contracts are published three or more years after the contract year. A search over recent dates does not include them.
- `isLikelyPerson` is a heuristic. In rare cases a company with an unusual name is hidden, or the reverse.

### Source code

The code is open source on GitHub: [JoaoPinto1/contratos-publicos-pt](https://github.com/JoaoPinto1/contratos-publicos-pt).
The repository also explains how the data source was chosen and how each field is normalized.
Bugs and suggestions: open an issue there or in the **Issues** tab of this page.

***

### Em português

Pesquise todos os contratos públicos celebrados em Portugal, publicados no Portal BASE, e receba dados limpos e estruturados: quem comprou o quê, a quem, por quanto e com que procedimento.

- **Filtros:** palavras-chave na descrição (sem distinguir maiúsculas nem acentos); entidade adjudicante e adjudicatário, por nome ou NIF; prefixos CPV; tipo de procedimento; datas de publicação; e preço.
- **Agendamento:** com **Só contratos novos**, cada execução devolve apenas os contratos publicados desde a anterior. Útil para alertas diários sobre concorrentes ou clientes.
- **Fonte:** os dados abertos que o IMPIC publica todas as semanas no dados.gov.pt. Por isso os contratos mais recentes chegam com até ~1 semana de atraso.
- **Privacidade:** o nome dos adjudicatários que são pessoas singulares é removido.
- **Preço:** paga por contrato devolvido. O campo **Máximo de contratos** limita o custo de cada execução.

Este actor não tem qualquer ligação ao IMPIC nem ao Portal BASE. O código é aberto: [github.com/JoaoPinto1/contratos-publicos-pt](https://github.com/JoaoPinto1/contratos-publicos-pt).

# Actor input Schema

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

Termos a procurar na descrição do contrato. Todos têm de aparecer; não distingue maiúsculas nem acentos.

## `contractingEntity` (type: `string`):

NIF (9 dígitos) ou parte do nome, por exemplo "Município de Coimbra".

## `contractor` (type: `string`):

NIF (9 dígitos) ou parte do nome da empresa.

## `cpvPrefixes` (type: `array`):

Prefixos de CPV, por exemplo "48" (software) ou "72" (serviços de TI).

## `procedureTypes` (type: `array`):

Por exemplo "Concurso público", "Ajuste direto", "Consulta prévia".

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

Data de publicação no BASE (AAAA-MM-DD). Por omissão, há 30 dias.

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

Data de publicação no BASE (AAAA-MM-DD). Por omissão, hoje.

## `minPrice` (type: `integer`):

Só contratos com preço contratual igual ou superior.

## `maxPrice` (type: `integer`):

Só contratos com preço contratual igual ou inferior.

## `onlyNew` (type: `boolean`):

Devolve só os contratos que ainda não foram devolvidos por uma execução anterior com os mesmos filtros. Útil para agendar o actor.

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

Limite de resultados por execução.

## Actor input object example

```json
{
  "keywords": "software",
  "onlyNew": false,
  "maxItems": 1000
}
```

# Actor output Schema

## `contracts` (type: `string`):

One item per public contract, with the fields described in the README.

# 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": "software"
};

// Run the Actor and wait for it to finish
const run = await client.actor("joaopinto/contratos-publicos-pt").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": "software" }

# Run the Actor and wait for it to finish
run = client.actor("joaopinto/contratos-publicos-pt").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": "software"
}' |
apify call joaopinto/contratos-publicos-pt --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,joaopinto/contratos-publicos-pt"
        }
    }
}
```

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/gue38hMegnySfnSKs/builds/stdITKKpFCPDzcb8Y/openapi.json
