SeniorLiving.News

Tuesday, August 4, 2026
America's News for Seniors
Vol. 14 · Issue 1483

API Documentation

Integration reference for connecting an analytics or CRM platform to SeniorLiving.News.

SeniorLiving.News can exchange data with one connected platform through two channels: export endpoints hosted on this site that the platform pulls from, and an ingest contract the platform implements so the site can push events to it in near real time. Both channels are disabled unless the site operator has configured a connection; there is no public or anonymous access to any of the data described here.

Authentication

Every request in both directions carries the same shared secret, arranged with the site operator, as a bearer token:

Authorization: Bearer <token>

Requests to the export endpoints with a missing or invalid token — or while no connection is configured — receive 404 Not Found, deliberately indistinguishable from the endpoint not existing.

Export endpoints (hosted by SeniorLiving.News)

GET https://seniorliving.news/api/export/status

Connection test. Verifies the bearer token against an active connection and nothing else — it reads no data and has no side effects, so it is safe to poll. Use this as the “test path” when configuring a platform's connection form.

{ "ok": true }

GET https://seniorliving.news/api/export/events

Raw first-party analytics events (pageviews, link clicks, engagement pings), paginated by an exact integer cursor. Events contain no personally identifying information — that is enforced when events are captured, not filtered at export time.

ParameterTypeDescription
after_idinteger ≥ 0Return events with id strictly greater than this. Default 0 (start from the beginning).
limitinteger 1–1000Maximum events per page. Default 500.
{
  "events": [
    {
      "id": 4182,
      "occurred_at": "2026-08-03T14:07:11.402Z",
      "event_type": "pageview",
      "visitor_id": "9f2c4a1e77b04d1c",
      "session_id": "b81d02c6a4e94f02",
      "path": "/briefing",
      "referrer": "https://news.google.com/",
      "props": null
    }
  ],
  "next_after_id": 4182
}

Pass next_after_id back as after_id to fetch the next page. When events comes back empty, next_after_id equals the cursor you sent — you are caught up. Ids are gap-free per row but not guaranteed contiguous; treat the cursor as opaque. A malformed query returns 400.

GET https://seniorliving.news/api/export/rollups

Daily metric rollups, computed on demand for a UTC date range. Nothing is precomputed or cached, so prefer modest ranges.

ParameterTypeDescription
fromYYYY-MM-DDFirst UTC day, inclusive. Must be a real calendar date.
toYYYY-MM-DDLast UTC day, inclusive. Must be ≥ from; the whole span may cover at most 92 days.
{
  "rollups": [
    {
      "date": "2026-08-03",
      "source": "seniorliving.news",
      "pageviews": 412,
      "unique_visitors": 63,
      "new_visitors": 9,
      "sessions": 120,
      "issue_number": 84,
      "top_pages": [{ "path": "/briefing", "views": 88 }],
      "link_clicks": 57,
      "avg_engagement_seconds": 74,
      "llm_usage": {
        "calls": 6,
        "failures": 1,
        "by_model": [
          {
            "model": "nvidia/nemotron-3-ultra-550b-a55b:free",
            "calls": 5,
            "failures": 1,
            "prompt_tokens": 60321,
            "completion_tokens": 24110
          }
        ]
      },
      "ga4": null
    }
  ]
}

top_pages lists at most ten paths by pageviews. avg_engagement_seconds is null on days with no engagement events. ga4 is reserved for Google Analytics figures and is currently always null. A quiet day returns zeros — the absence of a rollup, not zeros, signals a problem. A malformed or oversized range returns 400.

Ingest contract (implemented by the connected platform)

The connected platform exposes two endpoints under a base URL of its choosing. SeniorLiving.News calls them with the same bearer token.

POST {base}/v1/events

The site pushes events in JSON batches of up to 100. Each event carries a UUID id that serves as an idempotency key — retries can redeliver a batch, so the receiver must deduplicate on it.

[
  {
    "id": "5f0f9a3e-1c2b-4a6d-9e8f-0b1c2d3e4f5a",
    "type": "newsletter.signup",
    "occurred_at": "2026-08-03T14:03:22.512Z",
    "payload": { … }
  }
]

Any 2xx response means the entire batch is durably accepted. Any other response — or a network failure, or exceeding the 15-second request timeout — causes the site to retry the batch with backoff: after 1 minute, 10 minutes, 1 hour, 6 hours, then every 24 hours, giving up after 20 attempts. Delivery is near-real-time when the receiver is healthy and self-heals after an outage.

Newsletter events

newsletter.signup, newsletter.confirmed, newsletter.unsubscribed, and newsletter.bounced each carry the subscriber's contact record as the payload:

{
  "email": "pat@example.com",
  "first_name": "Pat",
  "last_name": "Rivera",
  "zip": "19103",
  "prefs": {
    "email": {
      "briefings": "daily",
      "puzzles": "daily",
      "onThisDay": "weekly",
      "local": "off"
    },
    "sms": { "enabled": false }
  },
  "status": "confirmed",
  "age_range": "65_74",
  "gender": null,
  "gender_self": null,
  "categories": ["health", "travel"],
  "profile_completed_at": "2026-08-03T15:12:09.000Z",
  "created_at": "2026-08-01T14:03:22.512Z",
  "confirmed_at": "2026-08-01T14:05:10.104Z",
  "unsubscribed_at": null
}
ParameterTypeDescription
statusenumpending · confirmed · unsubscribed · bounced
prefs.email.*enumCadence per item: off · daily · weekly
age_rangeenum | nullunder_55 · 55_64 · 65_74 · 75_84 · 85_plus
genderenum | nullwoman · man · non_binary · self_described (free text then in gender_self)
categoriesstring[]Any of: health, benefits, money, housing, caregiving, technology, travel, food
phonestring (absent by default)Present only when the subscriber opted into SMS and provided a number.

Analytics events

analytics.daily_rollup carries one UTC day's metrics — the payload shape is identical to a single entry in the export rollups endpoint above. One rollup is pushed per completed UTC day.

GET {base}/v1/llm-key

Lets the platform manage the site's language-model API key. The site fetches it only when no key is configured locally, and caches the response for 15 minutes.

{ "provider": "openrouter", "key": "sk-or-…", "expires_at": null }

Any non-200 response makes the site treat the managed key as unavailable and fall back to its reserve content. On a 401 from the LLM provider the site discards its cached key, refetches once, and retries once.

Data & privacy

Questions about integrating, or need credentials? Contact the site operator. This page documents the contract as currently deployed; breaking changes will be versioned under a new path prefix.