# BOE Alerts API: Spanish Gazette by Keyword (`oatpage/boe-sumario-reader`) Actor

Monitor Spain's Boletín Oficial del Estado (BOE) with named keyword rules. Get only new entries since your last run, classified as grants, public jobs, regulations or contracts, plus a daily digest. No login.

- **URL**: https://apify.com/oatpage/boe-sumario-reader.md
- **Developed by:** [Oatpage](https://apify.com/oatpage) (community)
- **Categories:** News, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 boe items

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

## BOE Alerts API: Spanish Gazette by Keyword

Independent tool. Not an official BOE service and not endorsed by the BOE.

Looking for new laws, grants (*subvenciones*), public jobs (*oposiciones*) or public contracts published in Spain's **Boletín Oficial del Estado (BOE)**? Set your keywords once and get only what is new since your last run, classified and with PDF, HTML and XML links. One clean row per entry: date, section, department, BOE identifier, title, rank and number. Uses the BOE open data API: no login, no proxy, no scraping.

**Search terms this Actor answers:** BOE alerts, BOE API, BOE scraper, Boletín Oficial del Estado, Spanish official gazette, Spain grants monitor, Spanish regulations tracker, BOE subvenciones, BOE oposiciones, BOE contratos.

### Use cases

- **Compliance and regulatory monitoring:** track new laws, royal decrees and ministerial orders that mention your sector (for example "protección de datos", "energía", "vivienda").
- **Grants and tenders lead generation:** list daily calls for grants (*subvenciones*, *ayudas*) and public contracts (Section V-A) and send them to your CRM or spreadsheet.
- **Legal alerts:** schedule a daily run with keywords and push new matches to Slack, e-mail or a webhook through Apify integrations.
- **Research and archives:** build a dated dataset of BOE publications by department or section.

### Alerts mode

Other BOE readers return the daily index and a keyword filter. This one is built to **watch** the gazette:

- **Named alert rules** (`watches`): several rules in one run, each with `keywords` (any), `mustInclude` (all), `exclude` (none), `sections`, `categories` and `department`. Each returned item lists the rules it matched in `alerts`.
- **Only new** (`onlyNewSinceLastRun` + `watchName`): remembers the last BOE date processed and reads only the days after it up to today. Schedule it daily. If more items match than `maxItems`, the position is not advanced, so nothing is lost.
- **Classification**: every item gets a `category` (normativa, subvenciones_ayudas, empleo_publico, convenios_colectivos, convenios_administrativos, contratacion, nombramientos, justicia, anuncios, otras_disposiciones), plus `rango` (Ley Orgánica, Real Decreto, Orden, Resolución...) and `numero` (e.g. 1028/2026) read from the title. Sections 2A, 2B, 4, 5A, 5B and 5C decide the category by themselves; in sections I and III the title decides. It is rule-based, so an odd title can land in `otras_disposiciones`.
- **Digest**: one `digest` record with counts per category and the departments with most items. Not billed.

Example input:

```json
{"onlyNewSinceLastRun":true,"watchName":"mis-alertas","watches":[{"name":"ayudas","categories":["subvenciones_ayudas"]}]}
```

Real output (BOE issues of 5-9 October 2026, 1213 items read; this rule matched 19; first match shown):

```json
{"fecha":"2026-10-06","seccion":"1","departamento":"MINISTERIO DE TRANSPORTES Y MOVILIDAD SOSTENIBLE","identificador":"BOE-A-2026-20744","titulo":"Orden TRM/1034/2026, de 1 de octubre, por la que se establecen adaptaciones y concreciones relativas a las ayudas a los sectores del transpo...","rango":"Orden","numero":"1034/2026","category":"subvenciones_ayudas","alerts":["ayudas"]}
{"type":"digest","dates":"2026-10-05..2026-10-09","items":1213,"byCategory":{"contratacion":306,"anuncios":295,"empleo_publico":172,"convenios_administrativos":112,"otras_disposiciones":105,"justicia":103,"nombramientos":78,"subvenciones_ayudas":19,"normativa":18,"convenios_colectivos":5},"topDepartments":[{"name":"MINISTERIO PARA LA TRANSICIÓN ECOLÓGICA Y EL RETO DEMOGRÁFICO","items":151},{"name":"MINISTERIO DE DEFENSA","items":144}]}
```

Each item still carries the links to the PDF, HTML and XML of the BOE. The actor reads the daily summary (titles), not the full text of each disposition.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `dateFrom` | string `YYYY-MM-DD` | today (Madrid) | First publication date. |
| `dateTo` | string `YYYY-MM-DD` | `dateFrom` | Last publication date. Maximum range: 92 days. |
| `sections` | array of strings | all | Section codes: `1`, `2A`, `2B`, `3`, `4`, `5A`, `5B`, `5C`. |
| `keywords` | array of strings | none | Keep items whose title contains at least one keyword (ignores case and accents). |
| `department` | string | none | Keep items whose department name contains this text (ignores case and accents). |
| `watches` | array of objects | none | Named alert rules (see Alerts mode). |
| `categories` | array of strings | all | Keep only these categories. |
| `onlyNewSinceLastRun` | boolean | `false` | Alerts: read only the days after the last run. |
| `watchName` | string | `default` | Name under which the last date is remembered. |
| `includeDigest` | boolean | `true` | Add the digest record (not billed). |
| `maxItems` | integer | 100 | Maximum number of items returned (and charged). |

Section guide: 1 general provisions; 2A appointments; 2B competitions and examinations; 3 other provisions; 4 justice administration; 5A public contracts and procurement; 5B other official announcements; 5C private announcements.

Example input:

```json
{
  "dateFrom": "2026-09-28",
  "dateTo": "2026-10-04",
  "keywords": ["subvención", "ayudas"],
  "maxItems": 50
}
```

More input examples:

```json
{ "dateFrom": "2026-10-01", "sections": ["5A"], "keywords": ["software", "servicios"], "maxItems": 100 }
```

Daily grants watch (schedule it every morning, no dates needed):

```json
{ "keywords": ["subvención", "ayudas", "convocatoria"], "sections": ["3", "5B"] }
```

Appointments and public exams of one ministry:

```json
{ "sections": ["2A", "2B"], "department": "Hacienda", "dateFrom": "2026-09-01", "dateTo": "2026-09-30" }
```

### FAQ

**How do I get a daily e-mail or Slack message?** Create a Schedule (daily, 09:00 Madrid) and add an Apify integration or webhook.
**Does it return the full legal text?** No, the summary metadata plus links; fetch `url_xml` for the text.
**Does it work on Sundays?** The BOE does not publish then, so the run returns nothing for those days.

### Output

One dataset item per BOE entry. Real example from a test run (28 Sep to 4 Oct 2026, 19 items returned):

```json
{
  "fecha": "2026-09-28",
  "seccion": "3",
  "seccion_nombre": "III. Otras disposiciones",
  "departamento": "MINISTERIO DE AGRICULTURA, PESCA Y ALIMENTACIÓN",
  "epigrafe": "Comunidad Autónoma de La Rioja. Convenio",
  "identificador": "BOE-A-2026-20134",
  "titulo": "Resolución de 22 de septiembre de 2026, de la Subsecretaría, por la que se publica el Convenio entre la Entidad Estatal de Seguros Agrarios, O.A., y la Comunidad Autónoma de La Rioja, para el intercambio de datos de los beneficiarios a efectos de gestión y control de subvenciones a los seguros agrarios.",
  "url_pdf": "https://www.boe.es/boe/dias/2026/09/28/pdfs/BOE-A-2026-20134.pdf",
  "url_html": "https://www.boe.es/diario_boe/txt.php?id=BOE-A-2026-20134",
  "url_xml": "https://www.boe.es/diario_boe/xml.php?id=BOE-A-2026-20134"
}
```

Titles and departments are in Spanish, as published.

### Pricing

Pay per event:

| Event | Price |
|---|---|
| Actor start | free |
| Result item | 0.001 USD (1 USD per 1,000 items) |

The Actor stops when it reaches `maxItems` or your maximum spend per run.

**Cost guide:** a typical run = items × 0.001 USD.

- One day, all sections (about 160 items on 2 Oct 2026): about 0.16 USD.
- One day, keyword "subvención" (a handful of items): well under 0.01 USD.
- One week with keywords (19 items in the test above): about 0.02 USD.
- A full month, all sections (several thousand items): a few USD.

Apify platform usage is separate and small: the Actor makes one request per day in the range.

### Known limits

- Reads the **daily summary** only (titles and metadata), not the full text of each disposition. Use `url_html` or `url_xml` to fetch it.
- Keyword filter applies to the title only.
- Days without a BOE issue (usually Sundays) are skipped.
- Maximum range per run is 92 days; for longer periods start several runs.
- Data depends on the availability and format of the BOE API; if the BOE changes it, the Actor may need an update.

### Source and legal notice

Data come from the **Agencia Estatal Boletín Oficial del Estado** open data service (https://www.boe.es/datosabiertos/), published for reuse under the BOE legal notice and reuse conditions (https://www.boe.es/informacion/aviso_legal/). This Actor adds no personal data; the BOE itself may publish names of people in appointments or announcements, and your use of them is subject to the data protection rules that apply to you. The Actor is independent and is not affiliated with or endorsed by the BOE.

**\[Legal 05-10] Reuse conditions of the BOE (legal notice, in force since 28 June 2024):**

- Attribution: write "Fuente de los datos: Agencia Estatal Boletín Oficial del Estado" when you reuse the data unmodified, or "Basado en datos de la Agencia Estatal Boletín Oficial del Estado" if you transform them.
- Do not alter the meaning of the information, and identify any change you make. This Actor only filters and restructures the summary fields; titles and departments are copied as published.
- Dating: each item carries `fecha` (BOE publication date). Show it, and the date you ran the Actor, when you republish.
- Do not use BOE logos or marks, and do not present your product as official or endorsed by the BOE.

**\[Legal 05-10] Personal data (GDPR / LOPDGDD):** items from Sections 2 (appointments, competitions), 4 (justice) and 5 (announcements and notices) can contain names, and sometimes partial ID numbers, of natural persons. The output is only what the BOE publishes, but you are responsible for what you store or process: define a lawful basis and a purpose, minimise the data, do not build profiles of individuals, respect retention limits and data-subject rights, and do not use it for unsolicited marketing. This is not legal advice.

### Support

Open an issue on the Actor page. Issues are answered within 14 days.

# Actor input Schema

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

First publication date (YYYY-MM-DD). Defaults to today (Madrid time).

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

Last publication date (YYYY-MM-DD). Defaults to dateFrom. Maximum range: 92 days.

## `sections` (type: `array`):

Section codes to include: 1, 2A, 2B, 3, 4, 5A, 5B, 5C. Leave empty for all sections.

## `keywords` (type: `array`):

Only items whose title contains at least one keyword (case and accent insensitive). Leave empty for no filter.

## `department` (type: `string`):

Only items whose issuing department name contains this text (case and accent insensitive), e.g. 'Hacienda'.

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

Maximum number of items to output (and be charged for).

## `watches` (type: `array`):

Optional. Several named alert rules in one run. Each rule: {"name":"...","keywords":\[any of these in the title],"mustInclude":\[all of these],"exclude":\[none of these],"sections":\["1","3"],"categories":\["subvenciones_ayudas"],"department":"hacienda"} with at least one criterion. Only items matching at least one rule are returned, each with the list of rules it matched in 'alerts'.

## `categories` (type: `array`):

Optional. Keep only these categories: normativa, subvenciones_ayudas, empleo_publico, convenios_colectivos, convenios_administrativos, contratacion, nombramientos, justicia, anuncios, otras_disposiciones.

## `onlyNewSinceLastRun` (type: `boolean`):

Remembers the last BOE date processed (per 'Watch name') and reads only the days after it up to today. Schedule it daily. If more items match than 'Max items', the position is not advanced so nothing is lost.

## `watchName` (type: `string`):

Name of this alert stream, for the remembered position. Use a different one for each stream you follow.

## `includeDigest` (type: `boolean`):

Adds one record (type 'digest') with the number of matching items by category and the departments with most items. Not billed.

## Actor input object example

```json
{
  "sections": [],
  "keywords": [],
  "maxItems": 100,
  "watches": [
    {
      "name": "ayudas",
      "categories": [
        "subvenciones_ayudas"
      ]
    },
    {
      "name": "energia",
      "mustInclude": [
        "energia"
      ],
      "exclude": [
        "nuclear"
      ]
    }
  ],
  "categories": [],
  "onlyNewSinceLastRun": false,
  "watchName": "default",
  "includeDigest": true
}
```

# Actor output Schema

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

No description

# 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 = {
    "watches": [
        {
            "name": "ayudas",
            "categories": [
                "subvenciones_ayudas"
            ]
        },
        {
            "name": "energia",
            "mustInclude": [
                "energia"
            ],
            "exclude": [
                "nuclear"
            ]
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("oatpage/boe-sumario-reader").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 = { "watches": [
        {
            "name": "ayudas",
            "categories": ["subvenciones_ayudas"],
        },
        {
            "name": "energia",
            "mustInclude": ["energia"],
            "exclude": ["nuclear"],
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("oatpage/boe-sumario-reader").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 '{
  "watches": [
    {
      "name": "ayudas",
      "categories": [
        "subvenciones_ayudas"
      ]
    },
    {
      "name": "energia",
      "mustInclude": [
        "energia"
      ],
      "exclude": [
        "nuclear"
      ]
    }
  ]
}' |
apify call oatpage/boe-sumario-reader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,oatpage/boe-sumario-reader"
        }
    }
}
```

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/f53KBUch7D4A78eNs/builds/unIKP1t0cskCbKjSr/openapi.json
