Skip to content

Features and Modes

Eric Slutz edited this page Jul 29, 2026 · 8 revisions

Features and Modes

PumpSync has one iOS app and one backend API that supports hosted service, real self-hosting, and synthetic demo/App Review flows.

iOS App Features

  • Stores Tandem Source credentials in the device Keychain with device-only accessibility.
  • Validates Tandem credentials through the configured backend.
  • Writes Tandem insulin and carbohydrate samples to Apple Health after the user grants HealthKit permission.
  • Uses local sync metadata and a rolling external-ID ledger to avoid duplicate Apple Health samples.
  • Lets users choose PumpSync Hosted through StoreKit or enter a self-hosted backend URL.
  • Provides settings, sync, privacy/data handling, diagnostics, and support surfaces.
  • Uses background processing configuration for daily sync work.
  • Supports App Intents shortcuts for PumpSync flows.

PumpSync does not read unrelated Apple Health data and does not use HealthKit data for advertising, marketing, or data mining.

Access Modes

Mode User experience Backend behavior Storage
PumpSync Hosted User subscribes or restores the PumpSync Hosted auto-renewable subscription in the iOS app. Backend validates the signed App Store transaction and issues a short-lived PumpSync service token. Azure Table Storage for hosted operational state.
Self-hosted User enters their own backend base URL in app settings. Backend deployed in SelfHosted mode issues a service token without App Store subscription verification. SQLite by default.
Synthetic demo/App Review User enters the public demo backend URL and demo Tandem credentials. Backend runs SelfHosted + SyntheticDemo; no Tandem network calls are made. SQLite by default.

Sign in with Apple is intentionally not part of the current access flow.

Service tokens are 12-hour JWTs stored in the device Keychain; the app silently creates a new session when one expires. Rotating a self-hosted backend's signing key therefore invalidates outstanding sessions only until the app next reconnects.

The backend reports its data source on the wire — capabilities and session responses carry dataSourceMode (tandemSource or syntheticDemo) — and the app labels a demo backend's connection status accordingly, so synthetic data cannot silently masquerade as pump data.

Backend Modes

The backend uses ASP.NET Core configuration binding. Environment variables use double underscores.

Mode PumpSync__BackendMode PumpSync__DataSourceMode PumpSync__StorageProvider
Hosted service Hosted TandemSource AzureTableStorage
Real self-hosting SelfHosted TandemSource Sqlite
Demo/App Review SelfHosted SyntheticDemo Sqlite

The same API, contracts, services, and normalization code are used in all three modes.

Route Contract

Hosted, demo, and self-host app-entered URLs include /api. PumpSync appends /v1/... endpoint paths, so the backend exposes API routes under /api/v1/....

Main routes:

  • GET /api/v1/capabilities
  • POST /api/v1/subscription/session
  • POST /api/v1/self-host/session
  • POST /api/v1/app-store/notifications
  • GET /api/v1/status
  • POST /api/v1/tandem/credentials/validate
  • POST /api/v1/sync/tandem

status, tandem/credentials/validate, and sync/tandem require the bearer token returned by subscription/session or self-host/session.

Data Handling

  • Tandem credentials remain on device except during active validate or sync requests.
  • The backend does not persist Tandem username, password, Tandem session cookies, Tandem access tokens, raw Tandem events, or normalized Tandem samples.
  • The iOS app discards raw and normalized Tandem payloads after Apple Health confirms the write.
  • Hosted backend storage is limited to operational state such as subscription entitlements, installation lookups, sync attempts, rate-limit buckets, App Store notification idempotency keys, and data-deletion audit rows.
  • Self-host SQLite stores the same operational state in the self-hosted database.
  • Sync attempts and rate-limit buckets accumulate until a data-deletion request removes the user's rows; there is no automatic time-based cleanup.

Clone this wiki locally