Recipe: Import sessions
Backfill sessions that happened outside the scan flow — a legacy system migration, or a shift someone forgot to clock. Imported sessions are always flagged so a manager can review them (is_flagged: true, flag_reason: "manual_api_entry", source: "api").
Create a session
Reference the operator by operator_ident (or operator_id) and the device by its device_id code. Provide check_in and check_out with ISO-8601 times:
curl -X POST https://api.briefqr.com/v1/sessions
-H "Authorization: Bearer bqr_live_..."
-H "Content-Type: application/json"
-d '{
"operator_ident": "NURSE01",
"device_id": "FRONT-DESK",
"location_name": "Ward A",
"check_in": { "time": "2026-05-30T08:00:00Z" },
"check_out": { "time": "2026-05-30T16:00:00Z" },
"break_minutes": 30,
"notes": "Imported from legacy system"
}' total_hours is computed for you. location_name is optional (or use location_id); check_out.time must be after check_in.time.
References must resolve — and match mode
| Field | Resolves to | Unknown → |
|---|---|---|
operator_ident / operator_id | an operator | 422 unknown_operator |
device_id | a device (by its code) | 422 unknown_device |
location_name / location_id | a location | 422 unknown_location / ambiguous_location |
A test key can only reference test objects and a live key only live objects; mixing returns 422 cross_mode_reference. Prove your import in test mode first, then reset and run it live.
Backfilling in bulk
Send one Idempotency-Key per source record so re-running a partial import doesn’t double-create:
for row in legacy_rows:
requests.post(
"https://api.briefqr.com/v1/sessions",
headers={**headers, "Idempotency-Key": f"legacy-{row['id']}"},
json={
"operator_ident": row["worker"],
"device_id": row["terminal"],
"check_in": {"time": row["in"]},
"check_out": {"time": row["out"]},
},
) Correcting a session
Editing a session re-flags it (flag_reason: "manual_api_edit") and recomputes total_hours:
curl -X PATCH https://api.briefqr.com/v1/sessions/{id}
-H "Authorization: Bearer bqr_live_..."
-d '{ "check_out": { "time": "2026-05-30T16:30:00Z" } }'