Webhooks

Respond to important events in near-real-time

Receiving webhook events is particularly useful for listening to asynchronous events such as creation/resolution of differences and discrepancies and changes to group status.

To start using webhooks, you'll need to register the endpoints you want to use in the Command Center. After you register them, Noyo can push real-time event data to your application’s webhook endpoint as they happen. Noyo uses HTTPS to send webhook events to your app as a JSON payload.

Events

Event nameEvent key
Snapshot status changedmember_snapshot.status_change
Snapshot Fulfillment Summary updatedmember_snapshot_carrier_fulfillment_status.status_change
Difference createddifference.created
Difference marked as a discrepancydifference.discrepancy
Difference resolveddifference.resolved
Difference replaceddifference.replaced
Group Createdgroup.created
Group Connection Request createdgroup_connection_request.created
Group Connection Request status changedgroup_connection_request.status_change
Group Disconnection Request createdgroup_disconnection_request.created
Group Disconnection Request status changedgroup_disconnection_request.status_change


Payload Structure

The webhook HTTP payload will include information in both its HTTP headers and its request body. Event payloads do not contain any PII or PHI. Noyo recommends using the corresponding GET endpoints when you receive any .created webhook.

Headers

The payload will be sent with the following HTTP headers:


{
  "Content-Type": "application/json",
  "x-noyo-signature": "ffd3bc72dea695cf2f9cf01c8956af048c293abd0112267edc1ef28178c567ef",
  "x-noyo-timestamp": "2024-05-08T21:27:45.039587+00:00",
  "x-cloud-trace-context": "54d5ec040d178633b8594fcda9d0edc6/7396771996713220078",
}

Common fields

Each webhook event contains the following fields in the response body:

{
    "data": {
        "id": "eb73184b-ae3c-4411-aa82-3c3bd877cf78"
    },
    "event": {
        "id": "3573d31d-15ab-42a3-aece-8f1e3a5c986f",
        "created": 1714670277,
        "type": "difference.created"
    }
}

Some events may include additional fields.


Using webhooks to track enrollment changes

Our Tracking API and its webhooks enable you to build field-level change tracking, so you have complete transparency from the time Noyo initially processes the member snapshot to when we confirm the change was made successfully by the carrier. You can also listen for unexpected data discrepancies that could interrupt coverage for your members.

Events and webhooks in two scenarios: a completed change and an unexpected discrepancy

Member Snapshot status changed

{
    "event": {
        "id": "fbec86ad-ced9-48e5-9f77-4a3a00b522aa",
        "type": "member_snapshot.status_change",
        "created": 1719344385
    },
    "data": {
        "id": "ea1b3077-b4f9-461b-80be-28023bc8ea19",
        "status": "completed"
    }
}

Member Snapshot Fulfillment Summary updated

Read more about fulfillment summary here.

{
    "event": {
        "created": 1719858674,
        "id": "beb4e1b4-f1bd-4cbe-a361-a61bec3203e8",
        "type": "member_snapshot_carrier_fulfillment_status.status_change"
    },
    "data": {
        "carrier_id": "9a0a7437-4097-4251-9e71-85384c0eb1c9",
        "member_snapshot_id": "815e92bc-33c1-4ed3-b658-4dc0e56cc38a",
        "status": "sent"
    }
}

Difference created

For any snapshot sent to Noyo that contains changes, a difference.created event will be sent almost instantly after the snapshot is initially processed. This means you can save individual tracking identifiers for all field-level changes that are in-process.

Note that discrepancies found during carrier syncs will also initiate a difference.created event, so Noyo suggests calling GET difference to populate all relevant details of the difference, such as its source.

{
    "data": {
        "id": "eb73184b-ae3c-4411-aa82-3c3bd877cf78"
    },
    "event": {
        "id": "3573d31d-15ab-42a3-aece-8f1e3a5c986f",
        "created": 1714670277,
        "type": "difference.created"
    }
}

Difference marked discrepancy

If we detect that a processing change has not been made by the carrier, or we find a data discrepancy during a sync, Noyo will send a difference.discrepancy event.

{
    "data": {
        "id": "eb73184b-ae3c-4411-aa82-3c3bd877cf78"
    },
    "event": {
        "id": "98144317-718a-45cd-be96-0a400ecbc32e",
        "created": 1714670277,
        "type": "difference.discrepancy"
    }
}

Difference replaced

In cases where an open difference is replaced by another, Noyo will send an event that you can use to replace the association in your system.

{
    "data": {
        "id": "f50b03bb-c8ab-4dd9-92dc-5dcf77011e0c"
    },
    "event": {
        "id": "2ba88657-8bcc-4380-abc9-bbff85326ab2",
        "created": 1714670515,
        "type": "difference.replaced"
    }
}

Difference resolved

When a change is completed successfully by the carrier or a discrepancy is resolved (whether due to a subsequent snapshot, a sync, or a manual portal update, Noyo will send a difference.resolved event.

🚧

Once a difference is resolved, it cannot be reopened

{
    "data": {
        "id": "f50b03bb-c8ab-4dd9-92dc-5dcf77011e0c"
    },
    "event": {
        "id": "6b1b42fc-fc79-4a28-b94a-a63d3c9a611b",
        "created": 1714670515,
        "type": "difference.resolved"
    }
}

Group Connection Request created

{
    "event": {
        "id": "1586f9b4-63f1-4c20-a965-6677beb04396",
        "type": "group_disconnection_request.status_change",
        "created": 1719343992
    },
    "data": {
        "id": "2cfcf643-540e-45b7-9007-912ed53edc42",
        "status": "processing"
    }
}

Group Connection Request status changed

{
    "event": {
        "id": "2586f9b4-63f1-4c20-a965-6677beb04396",
        "type": "group_disconnection_request.status_change",
        "created": 1719343992
    },
    "data": {
        "id": "2cfcf643-540e-45b7-9007-912ed53edc42",
        "status": "action_required"
    }
}

Group Disconnection Request created

{
    "event": {
        "id": "3586f9b4-63f1-4c20-a965-6677beb04396",
        "type": "group_disconnection_request.status_change",
        "created": 1719343992
    },
    "data": {
        "id": "4cfcf643-540e-45b7-9007-912ed53edc42",
        "status": "action_required"
    }
}

Group Disconnection Request status changed

{
    "event": {
        "id": "4586f9b4-63f1-4c20-a965-6677beb04396",
        "type": "group_connection_request.status_change",
        "created": 1719343992
    },
    "data": {
        "id": "4cfcf643-540e-45b7-9007-912ed53edc42",
        "status": "processing"
    }
}

Subscriptions

Create a subscription

You can create webhook subscriptions in Command Center by going to Developer > Webhooks and pressing “New subscription”.

  • Under “Destination”, type the URL where you’d like to receive webhooks
  • Under "Secret", type a string to use as a secret key. You should choose a random string of text with high entropy. You can use the webhook secret to limit incoming requests to only those originating from Noyo. You may optionally provide an API key name to assist in future key rotation

Testing

🚧

Webhooks are not available for sandbox environments

Send a test event for a subscription

You can send a test request to any subscription through Command Center.

The payload will resemble the following:

{
    "data": {
        "message": "Hello world!"
    },
    "event": {
        "type": "test.hello_world",
        "created": 1715203664,
        "id": "beda9ea3-5136-4b7b-93be-37bf3fcc010a"
    }
}

Best Practices

Event delivery and ordering

New event types will be continuously added; it is up to you to decide which events you want to process and how, but your implementation of the event listener must be able to handle new event types without breaking.

We guarantee at-least-once delivery of events, meaning webhook endpoints may occasionally receive duplicate events. All event requests include an event ID, which may be used to deduplicate webhook events.

We do not guarantee delivery of events in the order they happen. You should also use the Noyo REST APIs to fetch any missing data.

Verification

Authenticate all requests to your webhook endpoint.

Noyo includes an HMAC signature with each outgoing webhook request in an x-noyo-signature HTTP header. Endpoints should verify each request by: computing an expected HMAC signature for the payload and verifying that the value contained in the x-noyo-signature header provided by the sender matches the expected signature. Read more.

Responding to webhooks

In order to prevent unnecessary retries, we recommend receiving webhook events and processing them in separate processes. Upon receiving the event, you should immediately respond with a 200 indicating that the event was successfully delivered.

Subscription health and retries

  • When an event fails to deliver, its queue will handle retrying with backoff 15 times over 3 days.
  • When a webhook fails delivery, its subscription is moved into unhealthy status
    • If an event succeeds, the status is changed back to active
    • If an event comes in when a subscription has been unhealthy for 7 days, and that event fails, the subscription is changed to “failed.” The subscription’s queue is paused, which means that no other events will be attempted

What’s Next

Learn how to verify webhooks