Recipe: Export hours
Pull completed sessions and push them into payroll. Two ways to do it: poll the API, or subscribe to session.completed webhooks for push delivery.
Poll completed sessions
Filter by status and since (updated-at watermark), and follow the cursor:
curl "https://api.briefqr.com/v1/sessions?status=completed&since=2026-06-01&limit=100"
-H "Authorization: Bearer bqr_live_..." import os, requests
def export_since(watermark: str):
base = "https://api.briefqr.com/v1/sessions"
headers = {"Authorization": f"Bearer {os.environ['BRIEFQR_KEY']}"}
cursor = None
while True:
params = {"status": "completed", "since": watermark, "limit": 100}
if cursor:
params["cursor"] = cursor
page = requests.get(base, headers=headers, params=params).json()
for s in page["data"]:
yield s
if not page["has_more"]:
break
cursor = page["next_cursor"] The fields you need
Each session carries the operator, hours, and timestamps:
{
"object": "session",
"id": "…",
"status": "completed",
"operator": { "id": "…", "ident": "NURSE01", "name": "Jane Doe", "employee_id": "E-1" },
"location": { "id": "…", "name": "Ward A" },
"check_in": { "time": "2026-06-02T08:00:00Z", "lat": 51.5, "lng": -0.1 },
"check_out": { "time": "2026-06-02T15:30:00Z", "lat": 51.5, "lng": -0.1 },
"total_hours": 7.5,
"break_minutes": 30,
"is_flagged": false,
"flag_reason": null,
"source": "scan"
} Map operator.employee_id (or ident) to your payroll id, and total_hours to the pay line. Check is_flagged — a flagged session (missing GPS, manual entry, edited) may warrant review before you pay it.
Keep a watermark
Persist the largest check_out.time (or your run timestamp) and pass it as since next run so you only fetch new/updated sessions. Prefer real-time? Subscribe to the session.completed and session.updated webhooks instead.