Developer API
Build on the same feed that powers Bluewatch.
A free, read-only JSON API of live UK firefighter recruitment. No auth, no rate limits, no account. Cached at the edge so it’s fast and stable. Build dashboards, mobile apps, Slack bots, custom widgets — whatever you like.
Base URL
https://bluewatch.app/api/v1Versioned. v1 is stable. Breaking changes ship under v2; v1 stays online.
Endpoints
/api/v1/opportunitiesList live recruitment opportunities. Most-recent first. Paginated.
https://bluewatch.app/api/v1/opportunities?role=wholetime®ion=north-west&limit=10/api/v1/opportunities/{slug}Single opportunity by slug. Slugs are stable once issued.
https://bluewatch.app/api/v1/opportunities/{opportunity-slug}/api/v1/servicesList services (fire and rescue services, airport ARFF units, defence fire teams, industrial fire teams, overseas employers).
https://bluewatch.app/api/v1/services?category=airport_arff/api/v1/services/{slug}Single service by slug. Use the slug from /jobs/fire/{slug} URLs.
https://bluewatch.app/api/v1/services/london-fire-brigade/api/v1/metaCounts and the latest opportunity timestamp. Cheap to poll for change detection.
https://bluewatch.app/api/v1/metaQuery parameters
/api/v1/opportunities
| Param | Values |
|---|---|
| service_type | fire (default), police, medicOnly fire is currently active. |
| service | A service sluge.g. london-fire-brigade — see /api/v1/services |
| role | wholetime, on_call, transferee, control, specialist, officer, cadet, volunteer, operational_hq |
| region | north-east, north-west, yorkshire-and-humber, east-midlands, west-midlands, east-of-england, london, south-east, south-west, scotland, wales, northern-irelandUK region — Wales rolls up the three Welsh services. |
| category | local_authority_frs, airport_arff, defence_fire, industrial, private_contractor, overseas_transfer, otherService category. |
| since | ISO 8601 timestampOnly return opportunities first seen at or after this time. |
| limit | 1–200Default 50. |
| offset | 0+For pagination. Default 0. |
/api/v1/services
| Param | Values |
|---|---|
| service_type | fire (default) |
| category | local_authority_frs, airport_arff, defence_fire, industrial, private_contractor, overseas_transfer, other |
| region | north-east, north-west, yorkshire-and-humber, east-midlands, west-midlands, east-of-england, london, south-east, south-west, scotland, wales, northern-ireland |
| limit | 1–200Default 50. |
| offset | 0+ |
Response shape
All endpoints return JSON. Lists are wrapped in { data, meta, links }; details in { data }.
Opportunity
{
"service_type": "fire",
"service_slug": "london-fire-brigade",
"service_name": "London Fire Brigade",
"service_short_name": "LFB",
"service_region": "London",
"service_category": "local_authority_frs",
"station_slug": null,
"station_name": null,
"slug": "lfb-2026-wholetime-intake",
"title": "Wholetime firefighter — 2026 intake",
"summary": "Applications open for the LFB 2026 wholetime intake.",
"role_type": "wholetime",
"specialism": null,
"is_cadet": false,
"status": "live",
"posted_at": null,
"closes_at": "2026-06-30T23:59:59.000Z",
"first_seen_at": "2026-04-21T09:30:00.000Z",
"last_seen_at": "2026-05-07T08:00:00.000Z",
"apply_url": "https://...",
"source_url": "https://...",
"url": "https://bluewatch.app/jobs/fire/london-fire-brigade/lfb-2026-wholetime-intake"
}Service
{
"service_type": "fire",
"service_category": "local_authority_frs",
"slug": "london-fire-brigade",
"name": "London Fire Brigade",
"short_name": "LFB",
"country": "UK",
"region": "London",
"website_url": "https://www.london-fire.gov.uk",
"recruitment_url": "https://www.london-fire.gov.uk/jobs/",
"description": null,
"url": "https://bluewatch.app/jobs/fire/london-fire-brigade"
}Examples
curl
curl 'https://bluewatch.app/api/v1/opportunities?role=on_call&limit=5'JavaScript (fetch)
const res = await fetch(
'https://bluewatch.app/api/v1/opportunities?service_type=fire®ion=south-west',
);
const { data, meta, links } = await res.json();Python
import requests
r = requests.get(
"https://bluewatch.app/api/v1/opportunities",
params={"role": "wholetime", "limit": 25},
)
r.raise_for_status()
for opp in r.json()["data"]:
print(opp["service_name"], "-", opp["title"])Caching, polling, errors
- Cached at the edge.Lists for 5 minutes, details for 10. Set your polling cadence accordingly — hitting more often gets you cached responses, not fresher ones.
- Change detection. Hit
/api/v1/metafirst and comparelatest_opportunity_atbefore re-fetching big lists. - CORS allowed for any origin. Browser apps can fetch directly — no proxy needed.
- Errors are JSON with
{ error: { code, message } }and a 4xx status. - Fair use.No formal limits, but if you’re hammering it harder than the cache TTL, that’s wasted effort — you’re hitting the same cached payload.
Attribution
The data is free to use. We’d love a link back to bluewatch.app in your UI — it helps applicants discover the source and keeps the project sustainable. The data is sourced live from each fire and rescue service’s own recruitment pages; treat each opportunity’s apply_url as the authoritative submission destination.
Building something? We’d love to hear about it.
If you’re building on the API and need a missing field, a different filter, or are running into a quirk, drop us a line. We can usually ship changes the same day.
hello@bluewatch.app