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 name | Event key |
---|---|
Snapshot status changed | member_snapshot.status_change |
Snapshot Fulfillment Summary updated | member_snapshot_carrier_fulfillment_status.status_change |
Difference created | difference.created |
Difference marked as a discrepancy | difference.discrepancy |
Difference resolved | difference.resolved |
Difference replaced | difference.replaced |
Group Created | group.created |
Group Connection Request created | group_connection_request.created |
Group Connection Request status changed | group_connection_request.status_change |
Group Disconnection Request created | group_disconnection_request.created |
Group Disconnection Request status changed | group_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](https://files.readme.io/85ad564-Frame_58.png)
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
- If an event succeeds, the status is changed back to
Updated 2 months ago