Skip to content

"TandemSourceApi HTTP 404" - Requires Migration to tconnectsync v3.0.0 #146

Description

@ConnorGriffin

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 (assignmentIdtconnectDeviceId, maxDateOfEventsmaxDateWithEvents, 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions