Roster

Roster

Rules & Integration — admin
Conversion rules
Add a rule
State rules
Carrier factors
Developer / V1
Theme preview

Header matching

Which column headers in a broker's file map to each Plansight field. Matching is case-insensitive and ignores _ - . and extra spaces. Add more spellings on the “Add a rule” tab.

Value conversions

How messy cell values become canonical values. Every rule carries provenance — the carrier/file that taught it.

Household rule — same_household → Ideon

Ideon requires a same-household flag on every dependent. We set it per relationship — not from the broker's yes/no — so a spouse/partner is never accidentally dropped from the quote.

Add a rule

Compose a new header spelling or value conversion here — no code. It builds the exact rule and lets you download the updated rules file to hand to a developer (or drop into the repo). Live in-app editing is the next step once the rules store lands.

Ideon business rules — what they are & how Roster uses them

The small-group enrollment rules Ideon applies at quote time, extracted from the carrier business_rule_sets feed (2026 Q3, all 51 states). This is the census-side view of the master catalog aca-data-project/BUSINESS-RULES-AND-SELF-QUOTING.md. Enforce = Roster acts at import · Flag = warns, never blocks · Info = shown for reference · Rate = matters only when premiums are built (passed through untouched).

Per-state envelope

The extremes across every carrier/plan in a state — what Roster can assert before a specific carrier is chosen. Rules resolve per plan at quote time; a dependent over the age cap can't enroll in any plan, which is why Roster ages them off at import.

Statutory disability & paid family leave

States where employers have statutory obligations — mandated disability insurance and/or paid family & medical leave. Census members living in these states are flagged in the importer's residency panel (and carried in the payload), because obligations follow where members live — and Plansight carries the matching plan types (nyDisability, spfl).

Carrier composite factors

For small-group community-rated quoting: which carriers in a state can bill on composite (one blended rate per tier) vs list-billed (per member) only. A carrier that publishes composite factors can do composite; if it has none, it's list-billed only. Factors are the 4-tier multipliers relative to Employee only = 1.0. Source: the Ideon issuer feed (latest quarter per state).

Connect Roster to V1

Roster is a modal overlay, like Flatfile/Scout: one script tag, one call, one callback. Roster hosts no data — the widget parses in the browser and hands the clean payload back.

1. Mint a short-lived JWT (server-side)

use Firebase\JWT\JWT;
JWT::encode([
  'iss' => 'plansight-v1', 'aud' => 'plansight-roster',
  'exp' => time() + 300,                       // 5 min
  'context' => ['rfpId' => $rfpId, 'groupId' => $groupId],
], env('ROSTER_SIGNING_KEY'), 'HS256');

HS256, shared secret, ~5-min TTL, audience plansight-roster, issuer plansight-v1. Never ship the key to the browser.

2. Drop in the launcher

<script src="https://plansight-roster-stage.vercel.app/embed.js"></script>
<script>
  PlansightRoster.open({
    token: "{{ mintRosterJwt() }}",
    schema: "aca-medical-census",          // or "disability-census" / "carrier-rep-import"
    state: "{{ $group->state }}",          // census: employer state (drives age-out rules)
    effectiveDate: "{{ $rfp->effective_date }}",   // census: YYYY-MM-DD
    planOptions: {{ $group->plan_options }},       // census: available medical plan options
    offices: {{ $brokerage->office_names }},       // carrier-rep: the brokerage's offices
    onSuccess: (payload) => {              // census: payload.employees (EN shape)
      // carrier-rep: payload.records (RfpDistributionListDefaults shape)
    },
    onCancel: () => {},
  });
</script>

3. Endpoints

4. The payload & Ideon mapping

Roster returns the Employee Navigator Quote Census v1 shape — the same shape V1's EN sync already consumes. V1 derives the Ideon /quotes request from it.

Ideon fieldFrom our payload
external_idplansightMeta.eeId
date_of_birthdemographics.birthDate (YYYY-MM-DD)
genderdemographics.sex → M / F (Unspecified must be resolved)
zip_codedemographics.addresses.homeAddress.postalCode
fips_code / location_idV1 computes from ZIP/state
cobra / retireeplansightMeta.cobra / .retiree
last_used_tobaccodemographics.tobaccoUseInformation.lastUsedDate
dependents[].relationshipSpouse→spouse, Child→child, LegalDependent→ward
dependents[].same_householdPer relationship (see Household rule): Spouse/partner → true, all others → false

5. Error events (via the callback)

token_expired — mint a fresh JWT · schema_unknown — bad schema id · network_failed — Roster API unreachable.

Preview the embed theme

Roster restyles itself to match the app it's embedded in — it's all CSS design tokens (color, corners, font), so no host CSS is touched. Pick a host style or nudge the knobs; the live preview below is the real importer in that theme. The host applies whatever you land on via PlansightRoster.open({ theme: … }) — copy the snippet.

The preview below is live and clickable — or hit Open full importer to demo to launch it full-screen in its own tab (upload a census, click through, print) with these exact theme settings. That URL is also shareable for a demo: