Summary
Tandem silently removed the api/reports/reportsfacade/* endpoints and replaced them with api/reports/bff/*. As of June 30, 2026, pump_event_metadata() returns HTTP 404 and the entire sync flow fails.
TandemSourceApi HTTP 404 response: <html><head><title>404 Not Found</title></head>...
tconnectsync.api.common.ApiException: TandemSourceApi HTTP 404 response (HTTP 404)
Traceback lands here:
File ".../tconnectsync/sync/tandemsource/choose_device.py", line 14, in choose
pumpEventMetadata = tconnect.tandemsource.pump_event_metadata()
File ".../tconnectsync/api/tandemsource.py", line 415, in pump_event_metadata
return self.get('api/reports/reportsfacade/%s/pumpeventmetadata' % (self.pumperId), {})
New endpoints (confirmed from browser HAR)
1. Device/pump listing
Old: GET api/reports/reportsfacade/{pumperId}/pumpeventmetadata
New: GET api/reports/bff/pumper/{pumperId}
Old response was a flat list of pump dicts. New response:
{
"firstName": "...",
"lastName": "...",
"pumps": [
{
"assignmentId": "...", // was: tconnectDeviceId
"serialNumber": "...",
"modelNumber": "...",
"softwareVersion": "...",
"maxDateOfEvents": "...", // was: maxDateWithEvents
"availableDataRange": {
"start": "...", // was: minDateWithEvents
"end": "..."
},
"lastUploadDate": "...", // was: lastUpload (string)
"settings": {
"details": {
"profiles": { ... }, // same structure as before
"globals": { ... }
}
},
...
}
]
}
2. Pump events
Old: GET api/reports/reportsfacade/pumpevents/{pumperId}/{deviceId}?minDate=YYYY-MM-DD&maxDate=YYYY-MM-DD&eventIds=...
Returns: raw binary blob decoded by eventparser
New: GET api/reports/bff/pump-logs/{deviceId}?pumperId={pumperId}&startDate=YYYY-MM-DDT00:00:00Z&endDate=YYYY-MM-DDT23:59:59Z&eventIds=...
Returns: structured JSON
{
"events": [
{
"deviceAssignmentId": "...",
"eventCode": 279,
"sequenceGroup": 0,
"sequenceNumber": 2557306,
"pumpDateTime": "2026-06-30T00:02:44",
"estimatedDateTime": "2026-06-30T07:07:44Z",
"eventProperties": {
"commandedRateSource": 0,
"commandedRate": 0,
"profileBasalRate": 600,
"algorithmRate": 65535,
"tempRate": 65535
}
},
...
]
}
eventProperties field names match the existing eventparser attribute names (camelCase vs snake_case aside). Sample events for the types tconnectsync cares about:
| eventCode |
class |
key eventProperties fields |
| 279 |
LidBasalDelivery |
commandedRateSource, commandedRate, profileBasalRate, algorithmRate, tempRate |
| 256/399/372 |
LidCgmData{Gxb,G7,Fsl2} |
glucoseValueStatus, currentGlucoseDisplayValue, cgmDataType, rate, algorithmState |
| 16 |
LidBgReadingTaken |
bg, iob, bgEntryType, selectedIob, targetBg, isf |
| 20 |
LidBolusCompleted |
completionStatus, bolusId, insulinDelivered, insulinRequested, iob |
| 64 |
LidBolusRequestedMsg1 |
bolusId, bolusType, correctionBolusIncluded, carbAmount, bg, iob, carbRatio |
| 48 |
LidCarbsEntered |
carbs (presumed — not observed in HAR) |
| 33/61/63 |
LidCartridgeFilled/CannulaFilled/TubingFilled |
(timestamp only needed) |
| 11 |
LidPumpingSuspended |
suspendReason, preSuspendState |
| 229 |
LidAaUserModeChange |
currentUserMode, previousUserMode, exerciseTime, exerciseChoice, requestedAction |
Note: insulinDelivered/insulinRequested are already floats in units (not milliunits), matching the existing LidBolusCompleted type annotations.
Additional breakage: WAF blocks requests with wrong Origin
The BFF endpoints return HTTP 403 ("The request is blocked") if Origin is https://tconnect.tandemdiabetes.com. The WAF enforces same-origin. Fix: api_headers() should send Origin: https://source.tandemdiabetes.com for BFF calls (or the origin should be updated globally since the old reportsfacade endpoints are gone).
What a fix looks like
Two changes needed:
1. api/tandemsource.py
pump_event_metadata(): call api/reports/bff/pumper/{pumperId}, extract pumps[], remap field names (assignmentId → tconnectDeviceId, maxDateOfEvents → maxDateWithEvents, etc.)
pump_events_raw(): call api/reports/bff/pump-logs/{deviceId} with startDate/endDate (ISO8601 with time) instead of minDate/maxDate
api_headers(): update Origin to https://source.tandemdiabetes.com
2. Binary eventparser path
The new endpoint returns structured JSON, not a binary blob. decode_raw_events + Events will need a JSON-compatible path. The eventProperties dict keys match the eventparser attribute names closely (camelCase → the *Raw integer fields), so mapping is mechanical but touches the core parsing pipeline.
Workaround
For anyone blocked: the field/URL mapping above is enough to write a shim that bypasses the broken methods and produces eventparser-compatible objects by dispatching on eventCode and setting attributes from eventProperties.
Environment: tconnectsync 2.3.4, confirmed broken as of 2026-06-30.
Summary
Tandem silently removed the
api/reports/reportsfacade/*endpoints and replaced them withapi/reports/bff/*. As of June 30, 2026,pump_event_metadata()returns HTTP 404 and the entire sync flow fails.Traceback lands here:
New endpoints (confirmed from browser HAR)
1. Device/pump listing
Old:
GET api/reports/reportsfacade/{pumperId}/pumpeventmetadataNew:
GET api/reports/bff/pumper/{pumperId}Old response was a flat list of pump dicts. New response:
{ "firstName": "...", "lastName": "...", "pumps": [ { "assignmentId": "...", // was: tconnectDeviceId "serialNumber": "...", "modelNumber": "...", "softwareVersion": "...", "maxDateOfEvents": "...", // was: maxDateWithEvents "availableDataRange": { "start": "...", // was: minDateWithEvents "end": "..." }, "lastUploadDate": "...", // was: lastUpload (string) "settings": { "details": { "profiles": { ... }, // same structure as before "globals": { ... } } }, ... } ] }2. Pump events
Old:
GET api/reports/reportsfacade/pumpevents/{pumperId}/{deviceId}?minDate=YYYY-MM-DD&maxDate=YYYY-MM-DD&eventIds=...Returns: raw binary blob decoded by
eventparserNew:
GET api/reports/bff/pump-logs/{deviceId}?pumperId={pumperId}&startDate=YYYY-MM-DDT00:00:00Z&endDate=YYYY-MM-DDT23:59:59Z&eventIds=...Returns: structured JSON
{ "events": [ { "deviceAssignmentId": "...", "eventCode": 279, "sequenceGroup": 0, "sequenceNumber": 2557306, "pumpDateTime": "2026-06-30T00:02:44", "estimatedDateTime": "2026-06-30T07:07:44Z", "eventProperties": { "commandedRateSource": 0, "commandedRate": 0, "profileBasalRate": 600, "algorithmRate": 65535, "tempRate": 65535 } }, ... ] }eventPropertiesfield names match the existing eventparser attribute names (camelCase vs snake_case aside). Sample events for the types tconnectsync cares about:commandedRateSource,commandedRate,profileBasalRate,algorithmRate,tempRateglucoseValueStatus,currentGlucoseDisplayValue,cgmDataType,rate,algorithmStatebg,iob,bgEntryType,selectedIob,targetBg,isfcompletionStatus,bolusId,insulinDelivered,insulinRequested,iobbolusId,bolusType,correctionBolusIncluded,carbAmount,bg,iob,carbRatiocarbs(presumed — not observed in HAR)suspendReason,preSuspendStatecurrentUserMode,previousUserMode,exerciseTime,exerciseChoice,requestedActionNote:
insulinDelivered/insulinRequestedare already floats in units (not milliunits), matching the existingLidBolusCompletedtype annotations.Additional breakage: WAF blocks requests with wrong Origin
The BFF endpoints return HTTP 403 ("The request is blocked") if
Originishttps://tconnect.tandemdiabetes.com. The WAF enforces same-origin. Fix:api_headers()should sendOrigin: https://source.tandemdiabetes.comfor BFF calls (or the origin should be updated globally since the old reportsfacade endpoints are gone).What a fix looks like
Two changes needed:
1.
api/tandemsource.pypump_event_metadata(): callapi/reports/bff/pumper/{pumperId}, extractpumps[], remap field names (assignmentId→tconnectDeviceId,maxDateOfEvents→maxDateWithEvents, etc.)pump_events_raw(): callapi/reports/bff/pump-logs/{deviceId}withstartDate/endDate(ISO8601 with time) instead ofminDate/maxDateapi_headers(): update Origin tohttps://source.tandemdiabetes.com2. Binary eventparser path
The new endpoint returns structured JSON, not a binary blob.
decode_raw_events+Eventswill need a JSON-compatible path. TheeventPropertiesdict keys match the eventparser attribute names closely (camelCase → the*Rawinteger fields), so mapping is mechanical but touches the core parsing pipeline.Workaround
For anyone blocked: the field/URL mapping above is enough to write a shim that bypasses the broken methods and produces eventparser-compatible objects by dispatching on
eventCodeand setting attributes fromeventProperties.Environment: tconnectsync 2.3.4, confirmed broken as of 2026-06-30.