# Lloyd's of London Market Bulletins Monitor (`chosen_loafer/lloyds-market-bulletins-monitor`) Actor

Tracks Lloyd's of London Market Bulletins for new and updated bulletins, with firstSeen/lastSeen change tracking across runs. No personal data: the Signatory officer-name field published alongside each bulletin is never read or output.

- **URL**: https://apify.com/chosen_loafer/lloyds-market-bulletins-monitor.md
- **Developed by:** [Pavel Staurouski](https://apify.com/chosen_loafer) (community)
- **Categories:** Business, News, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 checked bulletin records

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

## Lloyd's of London Market Bulletins Monitor

Tracks **Lloyd's of London Market Bulletins** -- the official notices Lloyd's issues to
its own market (managing agents, brokers, coverholders): capacity-market rules, annual
charges/subscriptions, country-by-country regulatory changes, quarterly major-loss
reporting (QMR), byelaw/rulebook updates, and similar binding notices.

### What you get

One record per bulletin checked this run, tagged with an explicit `matchState`:
`FIRST_SEEN` (your own baseline run), `NEW` (published since your last check), `UPDATED`
(a previously-seen bulletin whose title, category, date or PDF link has changed),
`UNCHANGED` (re-confirmed, no change), or `REMOVED` (was present last time this Actor
checked that part of the archive, no longer there). Each record carries the bulletin's
own reference code (e.g. `Y5492`), title, category, published date, and a direct PDF
link.

### What it does not do

**No personal data, ever.** Each bulletin on the live page is published alongside a
"Signatory" column naming the individual Lloyd's officer who issued it (e.g. "Rizwan
Kermali"). This Actor's parser never extracts that column's text into memory at all --
there is no code path anywhere in `src/` that reads the Signatory cell, so there is
nothing to redact after the fact. A second, independent guard (`_shared/pii.js`'s
key-based stripper, reused from this project's other Actors) is also applied to every
output record before it is pushed, as a structural safety net against a future code
change accidentally reintroducing a signatory-shaped field.

**The source is the live bulletins search, not a bulk archive download.** Lloyd's
publishes this as a paginated search widget (~274 pages, ~10 bulletins/page, ~2,740
bulletins total as of this Actor's build date), not a single downloadable file. This
Actor checks the most recent pages by default (see `maxPages` below) rather than
crawling the full archive on every run.

### Why you might need this

Market Bulletins are binding on everyone operating in the Lloyd's market -- missing one
(a charge deadline, a country-specific authorisation change, an updated capacity rule)
is a real compliance and operational risk, not just an inconvenience. This Actor exists
so you find out the moment a new or changed bulletin is published, on your own schedule,
instead of manually re-checking the bulletins page.

### Input

```json
{
  "maxPages": 5,
  "maxChecked": 100
}
```

- `maxPages` (default 5): how many pages to check this run, most recent first (~10
  bulletins/page). A routine scheduled run rarely needs more than the default: the Actor
  stops early, before using the full budget, once it reaches a page it has already seen
  with no changes (everything older is necessarily already known too, since the source is
  sorted newest-first). Raise this for a deeper historical backfill on your first run.
- `maxChecked` (default 100): a hard, independent cap on how many bulletin rows are
  inspected (and charged) this run.

### Sample output

One real bulletin (captured in this Actor's own test fixture, `test/fixtures/page1-live.html`,
from the live bulletins search), run through this Actor's own `buildBulletinRecord()` as its
first-ever run against that bulletin (hence `matchState: "FIRST_SEEN"`; a later run that finds
this same bulletin unchanged or edited would report `UNCHANGED` or `UPDATED` instead, never
`FIRST_SEEN` again):

```json
{
  "bulletinId": "Y5492",
  "title": "Y5492 - Q3 2026 QMR - major loss, exchange rate and other information",
  "description": "Q3 2026 QMR - major loss, exchange rate and other information",
  "category": "Finance Risk Mgmt and Operations",
  "publishedDate": "2026-10-01T00:00:00.000Z",
  "pdfUrl": "https://uksprctx112strgacc.blob.core.windows.net/media-651c0e64-c1d0-4f97-90f7-883c69fe2ef2/d4f7e723-1a2e-415b-869d-c602f0561a6e/Y5492.pdf",
  "matchState": "FIRST_SEEN",
  "firstSeenAt": "2026-10-09T21:30:00.000Z",
  "lastSeenAt": "2026-10-09T21:30:00.000Z",
  "checkedAt": "2026-10-09T21:30:00.000Z",
  "sourceUrl": "https://www.lloyds.com/market-resources/market-bulletins"
}
```

Note the absence of any Signatory-officer field, per "What it does not do" above.

### Change tracking across runs

Run this Actor on a schedule (weekly is more than enough given Lloyd's own real
publishing cadence of roughly 1-3 bulletins/week). Each bulletin's first-seen/last-seen
timestamps and last-known content are stored per Actor, so a later run only reports what
actually changed, not a re-dump of everything checked.

**REMOVED is only ever reported within the page range a run actually re-checks.** This
Actor does not re-crawl the full ~274-page archive every run (that would be slow and
expensive for essentially a static, append-only publication history). If a bulletin
further back in the archive than this run's early-stop point is ever withdrawn, this
Actor will not notice until a run's page range happens to reach that far again (e.g. a
deliberately large `maxPages` value). In practice, Lloyd's own bulletin archive is
append-only -- bulletins are not routinely withdrawn -- so this limitation rarely matters;
it is documented here rather than silently assumed away.

### Pricing

Pay per run started, plus per bulletin record produced (new, updated, unchanged, or
removed). See the Pricing tab for exact rates.

# Actor input Schema

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

How many pages of the live bulletin list to check this run (most recent first, ~10 bulletins per page). A routine scheduled run only needs enough pages to catch bulletins published since your last check -- the Actor stops early once it reaches a page it has already seen with no changes. Increase this for a deeper historical backfill on your very first run.

## `maxChecked` (type: `integer`):

Hard cap on how many individual bulletin rows are inspected (and charged) this run, independent of Max pages per run.

## Actor input object example

```json
{
  "maxPages": 5,
  "maxChecked": 100
}
```

# Actor output Schema

## `bulletinResults` (type: `string`):

Per-bulletin records for this run.

# 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("chosen_loafer/lloyds-market-bulletins-monitor").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("chosen_loafer/lloyds-market-bulletins-monitor").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 chosen_loafer/lloyds-market-bulletins-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,chosen_loafer/lloyds-market-bulletins-monitor"
        }
    }
}
```

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/gL1F6o32zhh1Vdee6/builds/pHvrCjpiaf18DEhcl/openapi.json
