Skip to main content

Python: FireServiceRota / BrandweerRooster

Python 3 API wrapper for FireServiceRota and BrandweerRooster.

About

This package provides access to emergency incident data from FireServiceRota and BrandweerRooster — services used by firefighters.

Features:

  • Real-time incident notifications via WebSocket
  • User availability (duty schedule)
  • Incident response status (acknowledge / reject)
  • Pager management: list pagers, send messages, poll delivery status

A subscription and login account are required. See fireservicerota.co.uk or brandweerrooster.nl for details.

Installation

pip install pyfireservicerota

Authentication

Authentication uses OAuth2 tokens. On first use, exchange your credentials for a token_info dict and store it. After that you only need the tokens — use refresh_tokens() to keep them valid without re-entering your password.

First-time login

from pyfireservicerota import FireServiceRota, InvalidAuthError

api = FireServiceRota(
    base_url="www.brandweerrooster.nl",
    username="your@email.address",
    password="yourpassword",
)

try:
    token_info = api.request_tokens()
except InvalidAuthError:
    print("Invalid credentials")
    token_info = None

Subsequent use (stored tokens)

from pyfireservicerota import FireServiceRota

api = FireServiceRota(
    base_url="www.brandweerrooster.nl",
    token_info=token_info,  # dict loaded from storage
)

Refreshing tokens

Any API call can raise ExpiredTokenError or InvalidTokenError when the access token needs refreshing:

from pyfireservicerota import ExpiredTokenError, InvalidTokenError, InvalidAuthError

try:
    result = api.get_availability("Europe/Amsterdam")
except (ExpiredTokenError, InvalidTokenError):
    try:
        token_info = api.refresh_tokens()
    except InvalidAuthError:
        print("Refresh token invalid, re-login required")

Usage

Availability

availability = api.get_availability("Europe/Amsterdam")
print(availability)
# {"available": True, "type": "recurring", ...} or {"available": False}

Incidents

incident_id = 123456

# Get your response status for an incident
response = api.get_incident_response(incident_id)

# Acknowledge (True) or reject (False)
api.set_incident_response(incident_id, True)

Real-time incident notifications (WebSocket)

import time
from pyfireservicerota import FireServiceRotaIncidents

def on_incident(data):
    print(f"Incident received: {data}")

wsurl = f"wss://www.brandweerrooster.nl/cable?access_token={token_info['access_token']}"

listener = FireServiceRotaIncidents(on_incident=on_incident)
listener.start(url=wsurl)

while True:
    time.sleep(1)

Pagers

# List pagers linked to your account
pagers = api.get_pagers()
# [{"id": 7719, "user_id": 12345, "serial_number": "C202351.01045", "type": "Swissphone s.QUAD C35",
#   "battery_level": 79, "state": "powered_on", "signal_strength": -91, ...}]

# Send using the pager's own registered address (confirmation=True)
result = api.send_pager_message(6789, "Test alarm message", confirmation=True)
if result:
    print(f"Sent: id={result['id']} state={result['acknowledgment_state']} address={result['address']}")

# Send to a specific capcode address
result = api.send_pager_message(6789, "Test alarm message", address="1234567")

# Send to multiple capcodes
result = api.send_pager_message(6789, "Test alarm message", addresses=["1234567", "7654321"])

# With a delivery-status webhook
result = api.send_pager_message(
    6789,
    "Test alarm message",
    confirmation=True,
    webhook_url="https://your.server/pager-callback",
)

# Poll delivery status
if result:
    status = api.get_pager_message_status(6789, result["id"])
    if status:
        print(status["acknowledgment_state"])  # e.g. "automatic", "manual", "none"

Example script

example.py connects to www.brandweerrooster.nl and runs through the full API surface:

  1. Request OAuth2 tokens
  2. Fetch the most recent incident
  3. Get user availability
  4. Get and set incident response status (uses the most recent incident)
  5. List pagers, send a test message, poll delivery status
  6. Connect to the WebSocket and listen for live incident notifications

Run with environment variables (non-interactive):

FSR_USERNAME=your@email.nl FSR_PASSWORD=secret python example.py

Or interactively (prompts for credentials):

python example.py

Exceptions

Exception When raised
InvalidAuthError Wrong credentials or expired refresh token
ExpiredTokenError Access token expired or revoked — call refresh_tokens()
InvalidTokenError Access token invalid — call refresh_tokens()

Release files for pyfireservicerota 0.0.49

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyfireservicerota 0.0.49
File Size Uploaded
pyfireservicerota-0.0.49.tar.gz 9.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyfireservicerota 0.0.49
File Interpreter ABI Platform
pyfireservicerota-0.0.49-py3-none-any.whl Python 3 none any Details

Total release size: 18.3 kB

Release files / pyfireservicerota-0.0.49.tar.gz

Download URL pyfireservicerota-0.0.49.tar.gz
Size 9.4 kB
Tags Source
SHA-256 checksum
How to use checksums
652da7c2ddddac7e98583c3bf7e09aa0860d6d8356485856cfdd81df1866930d
BLAKE2b-256 checksum
How to use checksums
c3ec46273a55513cf65faa31b13f8a991d8de152c184460ba3b9ebbbfdc0b26a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / pyfireservicerota-0.0.49-py3-none-any.whl

Download URL pyfireservicerota-0.0.49-py3-none-any.whl
Size 8.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
037968bda5677d145997853ca3f12ae3339c1c65c89b46282db18f2094966bc8
BLAKE2b-256 checksum
How to use checksums
ca17e90dff40c7e1a2d68ec74812e78f3c07df9507ac634e5da7c605fdaacd92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

0.0.49 This release

2 release files

0.0.48

2 release files

0.0.44

2 release files

0.0.43

1 release file

0.0.42

1 release file

0.0.41

1 release file

0.0.40

1 release file

0.0.39

1 release file

0.0.38

1 release file

0.0.37

1 release file

0.0.36

1 release file

0.0.35

1 release file

0.0.34

1 release file

0.0.33

1 release file

0.0.32

1 release file

0.0.31

1 release file

0.0.30

1 release file

0.0.29

1 release file

0.0.28

1 release file

0.0.27

1 release file

0.0.26

1 release file

0.0.25

1 release file

0.0.24

1 release file

0.0.23

1 release file

0.0.22

1 release file

0.0.21

1 release file

0.0.20

1 release file

0.0.19

1 release file

0.0.18

1 release file

0.0.17

1 release file

0.0.16

1 release file

0.0.15

1 release file

0.0.14

1 release file

0.0.13

1 release file

0.0.12

1 release file

0.0.11

1 release file

0.0.10

1 release file

0.0.9

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page