The Tracking API

What is the Tracking API?

Noyo’s Tracking API introduces an easy way for ben-admin platforms to closely track the progress of in-flight enrollment changes and see data discrepancies. You’ll be able to tell whether a data difference between you and the carrier is inconsequential, worth keeping an eye on, or about to cause a major issue.

This API works by providing a granular view of the data differences between what you submitted and what the carrier has, and allows you to track a change more closely than you can with snapshot or transaction statuses alone.

The Tracking API is a companion to the member snapshot API and should be built after completing that integration. Member snapshots are idempotent and let you describe the current known state of a family’s coverages; this is the key to dynamically tracking data differences as they move toward resolution.

Let Noyo do the diffing for you

Data discrepancies are an unavoidable during enrollment processing today. While we all wish carriers would install each change perfectly, that’s not always the case. Letting discrepancies go unresolved can lead to missed enrollments, access-to-care problems, and billing issues.

Whether you already do change confirmation as part of your workflow today* or aspire to automatically distribute errors to your end customers to resolve, we recommend you build with our new Tracking API.

This API provides a unified, current view of individual field-level differences per carrier. Beyond reducing implementation time and cost, it leverages Noyo’s ever-improving comparison logic. We built these new endpoints because successful data comparison against a carrier requires doing two things well:

  1. Knowing how to compare the data
  2. Knowing how to contextualize and prioritize the differences identified

The former is not especially hard but can be tedious: you need to know which fields to map and how to normalize them. The latter is more difficult because it requires a deep understanding of carrier systems, rules, undocumented operational idiosyncrasies, permissiveness of retroactive logic, and so on. At Noyo we are experts on these nuances, with the benefit of understanding them across a wide network of carriers. Plus, we dedicate significant resources to keeping all this information up to date in our system.

* Some Noyo partners compare sent member snapshots with the member data returned in our GET endpoints. You could do this by looking at the dynamically calculated “Snapshot for Employee” endpoint along with the “Employee Status” endpoint. These might speed up the implementation of your comparison logic (and flag whether it needs doing in the first place).

When to use Tracking

  • You’re new to Noyo and are in the process of building your integration
    Tracking is a recommended follow-on implementation for our partners who prioritize the ability to track and confirm changes.
  • You’re migrating from a member request-based integration to using member snapshots and you want deeper visibility than status details can provide
    While snapshots and their associated transactions include the same statuses and status details you’re used to, the Tracking API will provide an additional layer of context for in-flight changes and provide clarity on which differences have become discrepancies.
  • You are trying to figure out how to compare sent snapshots with resulting member data
    We recognize that each consumer of this API may have different needs when it comes to confirming changes. If you’re considering building internal system functionality to compare data pre- and post- change, we recommend using the Tracking API instead. It will not only save time by leveraging Noyo’s built-in comparison logic, but it will include robust, dynamic analysis of each difference in the comparison and give you a clear sense of expected differences versus problematic ones (discrepancies).
  • You want to create your own tools for managing discrepancies
    Put discrepancy research and triage exactly where your end customers or internal teams need it most. The Tracking API makes it easy to pipe info on field-by-field differences into whatever interface you choose, and gives you detailed timelines, member data, and the ability to dismiss discrepancies that aren’t important.
  • You want to leverage Noyo Webhooks

Caveats

  • Tracking is only available to partners using member snapshots
    The Tracking API requires a declared current state for a family to identify differences and discrepancies. It will not be available for use with member requests due to the inherent limitations of that model. This also means that tracking is only available for changes being processed by snapshot-enabled carriers.
  • It is important to understand the Tracking API’s core concepts
    This API is designed to be flexible and powerful, which naturally comes with complexity. Several core concepts are explained below; please don’t hesitate to reach out to our team for further explanation if needed.

Core concepts

Tracking exposes the core type of a difference. A difference represents any field or fieldset that differs between your intended state and what the carrier has in their system.

A difference could reflect a pending field change that’s still in progress. Or there could be an expected carrier-specific behavior that creates a small temporary field mismatch. A difference could start as a pending change but become a discrepancy if the carrier fails to apply it and stops attempting to. We also raise discrepancies during routine carrier syncs.

To summarize:

A difference represents any field that is different in the carrier system than what you sent to Noyo as the intended state.

Differences can either be a) normal in-process changes or b) discrepancies, which have completed transactions (or no transactions) associated with them while fields are still mismatched.

The shape of a difference

{
  "id": "dd9a1813-34f7-4c7e-86bc-f041f2cbd9a1",
  "carrier_id": "b825cf4f-12b8-442f-af90-4c4483766d42",
  "difference_classification": "field_mismatch",
  "difference_type": "mailing_address",
  "impact_score": 4,
  "object_type": "employee",
  "object_id": "5200a894-81c5-4c41-8519-86c32e9a9965",
  "group_id": "f833ac4b-36aa-46f4-826c-0badcfe27922",
  "created": 1557329939,
  "modified": 1557329939,
  "discrepancy_time": 1641036540,
  "resolved": 1641036640,
  "fields": [
    {
        "key": "person.mailing_address.street_one",
        "platform_value": "870 E 800 N",
        "carrier_value": "#502"
    },
    {
        "key": "person.mailing_address.zip_code",
        "platform_value": "48097",
        "carrier_value": "84604"
    },
    {
        "key": "person.mailing_address.state",
        "platform_value": "UT",
        "carrier_value": "UT"
    },
    {
        "key": "person.mailing_address.city",
        "platform_value": "Provo",
        "carrier_value": "Provo"
    }
  ],
  "sources": [
    {
      "carrier_fetch_time": 1557329939,
      "difference_id": "75ed8e21-67b5-46d1-8c20-c0963cbc3695",
      "discrepancy": false,
      "last_seen": 1557329939,
      "member_snapshot_id": "d8eb17d4-24bf-4d7b-8542-8084a6b934b8",
      "object_id": "f603f552-7c77-45b1-a77d-b44281fd77af",
      "object_type": "member_transaction",
      "resolves_difference": false,
      "stage": "member_snapshot_sent_to_noyo"
    }, 
    {
      "carrier_fetch_time": 1557329939,
      "difference_id": "75ed8e21-67b5-46d1-8c20-c0963cbc3695",
      "discrepancy": true,
      "last_seen": 1557329939,
      "member_snapshot_id": "d8eb17d4-24bf-4d7b-8542-8084a6b934b8",
      "object_id": "f603f552-7c77-45b1-a77d-b44281fd77af",
      "object_type": "member_transaction",
      "resolves_difference": false,
      "stage": "member_snapshot_confirm"
    }, 
     {
      "carrier_fetch_time": 1641036540,
      "difference_id": "75ed8e21-67b5-46d1-8c20-c0963cbc3695",
      "discrepancy": true,
      "last_seen": 1641036540,
      "member_snapshot_id": "a9c01d76-019c-4c44-b414-a832246c014d",
      "object_id": "b6a1d883-394d-472d-a2d1-33b194b550ab",
      "object_type": "member_transaction",
      "resolves_difference": false,
      "stage": "member_snapshot_sent_to_noyo"
    }, 
    {
      "carrier_fetch_time": 1641036640,
      "difference_id": "75ed8e21-67b5-46d1-8c20-c0963cbc3695",
      "discrepancy": true,
      "last_seen": 1641036640,
      "object_id": "f603f552-7c77-45b1-a77d-fdsfsdfdsfdsfds",
      "object_type": "group_audit",
      "resolves_difference": true,
      "stage": "group_audit_complete"
    }
  ],
}

Classifications, types, and fields

There are three main classifications of differences: field_mismatch, missing_from_carrier, and missing_from_platform. Field Mismatches cover a wide array of general cases, and can represent any field on an individual or enrollment. Missing From Platform (your system) or Missing From Carrier can refer to an individual or an enrollment that is known to one system and not the other.

Difference types add specificity about what the mismatch is about or what type of thing is missing. In Field Mismatch cases this might be “address,” where in Missing From cases it might be “missing_dependent.”

The exact field path(s), along with known values in your system versus the carrier system, are included in the fields array. While the Tracking API is generally “field-level tracking”, some fields are grouped into a single difference for convenience, such as first/middle/last name or individual components of an address. Specific examples of these are provided here.

Important: Interpreting classifications and types

The classification and type use the factual nature of a difference to tell a story about where a change is in its lifecycle. It can require some interpretation to understand exactly what’s happening with a given change. For example, let’s look at a difference with the following fields:

{
	"difference_classification": "missing_from_carrier"
	"difference_type": "missing_ie" // missing enrollment
}

This table demonstrates how that difference should be interpreted across states:

discrepancy_timeresolvedexplanation
Pending changenullnullThe coverage is currently being added
Completed changenullsetThe coverage was added
Open discrepancysetnullMissing coverage in carrier system
Resolved discrepancysetsetMissing coverage issue was resolved

Lastly, note that the classification, type, and field array all describe the original difference, not dynamically updating data. For a resolved difference, the data provided about the field values will not be updated to match.

Sources

Member snapshots describe states that may require a change be initiated, but they do not prescribe changes. Multiple successive snapshots can also describe the same in-flight change. Because of these two dynamics, differences may span multiple snapshots or be resolved separately from processing a specific snapshot. Differences have their own lifecycle that aims to reflect the current state of the data in as close to real-time as possible.

Stages represent the part of the difference lifecycle where it was found. Noyo currently describes the following stages where creation, modification, discrepancy publishing, and closure can happen due to an event.

  • Snapshot sent to Noyo
    • member_snapshot_sent_to_noyo
  • Snapshot/transaction confirmation and completion
    along with any operational suppression
    • member_snapshot_confirm
    • member_snapshot_complete
  • Carrier syncs
    i.e. “Group Audits”
    • group_audit_complete

The source array is dynamic and new events will be added as they happen until the difference is resolved/closed:

  • A carrier sync that notices the difference’s ongoing existence will add to the stage array.
  • New member snapshots that describe a state involving the difference will add to the stage array.
  • The event that eventually closes the difference will add to the stage array.

Each item in the source array contains fields for when it happened, whether it resolved the difference, whether (at the time) the difference was considered a discrepancy, and whether or not the difference was marked for suppression.

Impact scoring

Noyo scores each difference to reflect its potential impact on the individual, group, and/or ben-admin platform. The impact score is a single number from 1 to 5, where 5 is considered the highest impact. In the Command Center, this score generates an “Impact” label:

API FieldCC “Impact” Label
5Urgent
4High
3Medium
2Low
1Info

While impact scoring is dynamic and may be refined over time, characteristic examples include:

  • A enrollment that is currently expected to be active but is completely missing in the carrier system will generally be scored 5.
  • An email address mismatch is currently scored at 1 , as these are usually a case of “work versus personal” address and do not affect deliverability.

As we work to continuously refine our scoring, more low-impact differences may be raised with newly offered carriers, specifically in areas like string capitalization, leading zeroes, and special characters.

For maximum flexibility, scoring is done independently of whether a difference has become a discrepancy. This allows you to use one without the other. For instance, you may choose to ignore Noyo’s discrepancy determination and instead use your own duration-based logic. Or you may wish to do your own scoring but still rely on Noyo to separate pending changes from discrepancies.

The Noyo scoring model

Specific scoring guidelines and logic are dynamically determined by Noyo and are not published. They reflect an ever-evolving understanding and analysis of carrier behavior and are not a stable mapping of simple type::impact pairings. Noyo periodically updates scoring logic and may re-score old differences to reflect the newest understanding of carrier-specific behavior.

Dates

Each difference includes a collection of relevant date fields.

FieldExplanation
createdWhen the difference was created (distinct from when it became a discrepancy)
modifiedLast modified
discrepancy_timeWhen the difference became a discrepancy. For some differences (e.g. those raised through carrier syncs), this will match created. For others (e.g. those that started as an in-flight change), this will be later than created.
resolvedWhen the difference was resolved
dismissedIf you have dismissed the difference, the timestamp of dismissal

Differences can represent field-level diffs at various stages of lifecycle. To determine whether a difference refers to a field that is currently being applied at the carrier or a discrepancy that is live, you can check for the existence of the discrepancy_time field.

If you want to determine whether a difference has been resolved or is otherwise no longer seen (agnostic of discrepancy status), we use resolved. This field provides a Unix timestamp of the resolution moment if resolved, and returns nothing if the difference is still open.

Dismissal and suppression

To help you design an effective triage workflow for your organization, differences support two distinct concepts: dismissal and suppression.

Dismissal is an action performed by your team in the Command Center. Dismiss a discrepancy if you no longer want to see it raised at its original level. The difference will still be available to you, but it may require additional filters in order to be included in responses. This is especially helpful if you’d like to raise dismissable notifications to individual end users.

Suppression is a similar concept, but is done by Noyo. Occasionally there is a difference raised during transaction processing that is flagged for internal Noyo review. Oftentimes the difference is in line with expected carrier behavior. For example, a carrier may not support a mid-month enrollment, so you would expect to see a start_date discrepancy for the member. Our system would recognize that though the discrepancy exists, it’s likely to be resolved on the first of the next month, so we would suppress it for that carrier. Similar to dismissal, these differences will still be available to you but may require explicit filtering.

Dismissal does not modify impact scoring, but suppression does. For example, Noyo may score most start date differences as a 5, but lower that to a 2 when matched to carrier logic and suppressed.

Transaction labeling and annotation

Suppression is closely correlated with situations that create “annotated transactions,” as discussed in our release notes from March 7, 2024.

Listing and filtering differences

The Tracking API currently supports pulling differences with the following filters:

  • Employee
  • Group
  • Transaction ID
  • Snapshot ID
  • Impact score (min, max)
  • Open vs. resolved
  • Discrepancies only vs. all differences

Resolving differences and discrepancies

Currently, differences cannot be resolved or closed through the Tracking API. They are only resolved when a) you update data in your system and send a new member snapshot that brings the data into alignment or b) the carrier makes an update in their system that brings the data into alignment.

We are actively working to bring resolution into our API, and plan to release webhooks soon that enable features like data editing and closing discrepancies. Our team will share more info as it becomes available, but we recommend keeping this in mind as you build.

In Command Center

⚠️

Details on how Command Center uses Noyo’s API is subject to change at any time. Like with other core Noyo concepts, Command Center may provide additional context for differences (including explanations of carrier-specific logic) that are not available via API.

To replicate the default list of discrepancies displayed by Command Center, filter for impact score ≥ 3 and is_discrepancy=true .

Discrepancies are shown at the member level in the Command Center - they will be flagged on a member’s page above their change history.

Webhooks

Read more about Tracking Webhooks here.

Examples and Recipes

API Reference