Customer Callback Example API

Introduction

Coverage Discovery is asynchronous. When you submit a Coverage Discovery request, the final result is not returned inline with the original request. Instead, you can receive the result in one or both of these ways:

  1. Callback delivery to your whitelisted callback URL
  2. Polling GET /rcm/eligibility/v1/coverage-discovery/{id}

Use this page only for callback and polling implementation details.

Use Developer Onboarding for whitelisting prerequisites and delivery-model planning.
Use Getting Started for first API calls and general headers.
Use Troubleshooting and Support for production issue triage.

Most customers reach this workflow through integrated Real-Time Eligibility. Direct Coverage Discovery submission is also supported, but it is typically an advanced pattern.

If your team is still building callback or polling support, ask about the temporary batch-file option described in onboarding. Optum can sometimes provide a secure batch file containing x12-271 responses produced from Real-Time Eligibility and/or Coverage Discovery as a proof-of-concept stop-gap.

This guide explains:

  • what is posted back to your system
  • how callback authentication works
  • how to tie a callback back to the originating Real-Time Eligibility or Coverage Discovery request
  • how to interpret the different CoverageDiscoveryTask result shapes
  • how tenant and subtenant context should be handled in callback processing
  • how polling fits alongside callbacks

How Integrated Real-Time Eligibility Feeds Coverage Discovery

For most customers, the callback payload exists because a prior Real-Time Eligibility request triggered Coverage Discovery automatically.

Operationally, that means your callback handler should expect many discovery task ids to originate from the real-time response link header rather than from a direct POST /coverage-discovery request.

Coverage Discovery Response Model

The payload posted to your callback endpoint uses the same CoverageDiscoveryTask model returned by:

GET /rcm/eligibility/v1/coverage-discovery/{id}

That means your implementation can use a single parser for:

  • callback payloads
  • polled discovery responses

The Main Fields You Should Read First

For most integrations, start with these fields:

  • id
    The Coverage Discovery task id. This is the primary identifier for the discovery record.
  • status
    The overall task status. Typical values are pending, success, or failure.
  • correlationId
    Echoes the original request correlation when one was supplied. This is the easiest way to tie the discovery result back to your originating workflow.
  • name
    The configured discovery task name assigned for your enrolled workflow.
  • startDateTime and endDateTime
    Show when the discovery task started and when it completed.
  • realTime
    Optional. Present when callback consolidation is enabled and the abbreviated parent Real-Time Eligibility result is included with the discovery record.
  • discoveryPaths
    The path-by-path discovery results. This is where you determine what happened during discovery.

How The Parent RTE Transaction Relates To CD Child Transactions

Coverage Discovery does not replace the original Real-Time Eligibility transaction. It extends it.

In an integrated flow:

  • the parent Real-Time Eligibility request is what originally triggered discovery
  • the parent Real-Time Eligibility response may be included in the callback under realTime when consolidated callback delivery is enabled
  • each executed Coverage Discovery path can produce its own child eligibility transaction under discoveryPaths.successful[*].transaction or discoveryPaths.unsuccessful[*].transaction

Think of the relationship this way:

  • realTime.transaction
    The abbreviated parent Real-Time Eligibility result that triggered or accompanied discovery
  • discoveryPaths.*[].transaction
    The related transaction details for individual discovery results

What The realTime Object Is For

The realTime object is optional and exists only for customers enrolled in consolidated callback delivery.

What it does:

  • carries related Real-Time Eligibility context alongside the discovery task
  • lets you correlate the discovery result back to the original real-time response without having to do a separate transaction lookup
  • preserves related real-time transaction details when included

What it does not do:

  • it does not replace the path-level discovery results
  • it is not guaranteed to be present for every customer or every callback

Most customers focus on identifiers, statuses, and the parts of the payload they need for operations and audit.

Understanding discoveryPaths

The discoveryPaths object groups path outcomes into four arrays:

  • successful
    Discovery paths that returned a successful coverage result.
  • unsuccessful
    Discovery paths that completed without a successful coverage result.
  • pending
    Discovery paths that have not completed yet.
  • skipped
    Discovery paths that were not executed.

Each path entry may contain:

  • id
    The discovery path record id
  • name
    The path name associated with that record.
  • timestamp
    When that path reached its current recorded state
  • reason
    Present on skipped paths to explain why they did not execute
  • transaction
    Present when transaction details are available and may include:
    • id
    • status
    • chcPayerId
    • x12-271

How To Read Root name Versus Path name

There are two different naming levels in the Coverage Discovery response:

  • root name
    Identifies the configured discovery task assigned for your tenant or subtenant. This is the enrolled workflow definition.
  • discoveryPaths.*[].name
    Identifies the specific discovery path that actually ran for that record.

Examples:

  • a task root name might be Medicaid + HMO
  • another task root name might be Commercial + HMO + RTCOB

Common Result Shapes

You should expect several valid shapes of the same model:

  • Success with one or more successful paths
    The root status is success, and discoveryPaths.successful contains one or more entries.
  • Failure with only unsuccessful paths
    The root status is failure, and discoveryPaths.unsuccessful contains one or more entries.
  • Failure with only skipped paths
    The root status can still be failure even when no downstream path executed because all configured paths were skipped.
  • Mixed path outcomes
    A successful task may still include both successful and unsuccessful path entries.
  • Consolidated callback with realTime
    The callback contains related real-time eligibility context under realTime, in addition to the discovery path results.
    Use realTime to review the related eligibility context and discoveryPaths.*[].transaction to review individual discovery result records.

Your parser should not assume:

  • only one successful path
  • only one unsuccessful path
  • that realTime is always present
  • that skipped means the overall task failed
  • that every path entry contains a transaction
  • that the root task status alone is enough for all business decisions

How Customers Tie Results Back To The Original Request

There are two main correlation methods, and many customers use both.

1. correlationId

If you send x-optum-correlation-id on the originating request, that value is the easiest way to tie later records back to your own transaction in:

  • callback headers as x-optum-correlation-id
  • callback body as correlationId
  • transaction search
  • discovery search

Recommended practice:

  • generate a unique correlation ID in your application
  • store it with your internal encounter or request record
  • use it as the primary join key when a callback arrives later
  • for integrated Real-Time Eligibility, also store the related real-time transaction id and any returned discovery task ids from the link header

2. Discovery Resource Path From Headers

You can also tie requests together using the returned discovery resource path.

When starting from Real-Time Eligibility

If you are enrolled in integrated Coverage Discovery and a Real-Time Eligibility request triggers discovery, the Real-Time Eligibility response may include a link header with one or more related discovery task resource paths.

Example pattern:

link: </coverage-discovery/0716e3e8-87ee-11ee-b9d1-0242ac120002>; title="coverage discovery - Task 1"; rel="related"

Use that related resource path to:

  • store the discovery task id immediately
  • poll GET /rcm/eligibility/v1/coverage-discovery/{id}
  • match a later callback payload whose body id is the same discovery task id

When starting from direct Coverage Discovery POST

If you submit POST /rcm/eligibility/v1/coverage-discovery directly, the initial asynchronous response returns a location header for the created task resource when a single task is created.

Example pattern:

location: /coverage-discovery/09876z5y-43x2-1w09-v8u7-tr6543s210qp

Use the location header to:

  • store the discovery task id
  • poll for status
  • match the later callback body id

Recommended Correlation Strategy

The most reliable production pattern is:

  1. Generate and send your own x-optum-correlation-id
  2. Store the returned discovery resource path:
    • link header when discovery was triggered from Real-Time Eligibility
    • location header when you submitted direct Coverage Discovery POST
  3. When a callback arrives, match on:
    • correlationId
    • discovery task id
    • optional parent realTime.transaction.id when consolidated callback delivery is enabled
    • child discovery transaction ids under discoveryPaths.*[].transaction.id when you need to reconcile individual result records
    • optional x-optum-subtenant-id when applicable

Data Tenancy And Subtenant Handling In Callbacks

The callback guide needs the same tenancy rules that apply everywhere else in the API.

Tenant Context

Enhanced Eligibility is a multi-tenant platform. Your tenant is assigned automatically through your Marketplace credentials and is echoed back in request processing and callback delivery as:

x-optum-tenant-id

For callback consumers, this means:

  • x-optum-tenant-id identifies the tenant context under which the original request was processed
  • your callback service should validate that this header matches the tenant you expect for that integration
  • clients should not invent or derive tenant ids; the value is controlled by Optum

In practice, this header is a data-isolation control as well as a troubleshooting aid.

Subtenant Context

Some customers operate under one tenant but need different configuration for downstream customers, facilities, or workflows. In those cases, Optum may assign one or more subtenant ids that are carried on requests and echoed back on callback delivery as:

x-optum-subtenant-id

Important callback rules:

  • this header is only present when the originating request used a configured subtenant
  • you should treat it as part of the routing and correlation context for that callback
  • you should not assume it is always present
  • you should not generate or infer subtenant values yourself

Think of the headers this way:

  • x-optum-tenant-id identifies your organization
  • x-optum-subtenant-id identifies the downstream customer, facility, or workflow context within your organization when one was configured

If your implementation serves multiple downstream customers or facilities, storing both values alongside the callback payload is the safest way to preserve data-tenancy context for auditing and support.

Callback Delivery Flow

End-to-End Sequence

  1. Your system submits either:
    • a Real-Time Eligibility request that may trigger integrated Coverage Discovery
    • or a direct Coverage Discovery request
  2. Enhanced Eligibility accepts the work.
  3. If callback delivery is configured, Enhanced Eligibility authenticates to your token endpoint.
  4. Enhanced Eligibility POSTs the completed CoverageDiscoveryTask payload to your whitelisted callback URL.
  5. Your system returns 204 No Content after successfully accepting and processing the payload.

If you are not using callbacks, or if you want a fallback validation path, you can poll the discovery resource directly.

Callback Authentication

Customers must expose a token endpoint that adheres to RFC 6749. This token endpoint must be whitelisted by Optum and is used to obtain a bearer token before callback delivery.

Token Request

Endpoint:
POST https://your-auth-server.com/token

Headers:

Authorization: Basic <base64(client_id:client_secret)>
Content-Type: application/x-www-form-urlencoded

Body:

grant_type=client_credentials

Token Response

The token endpoint must respond with 200 OK and a JSON body like:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": ""
}

The expires_in field is required because it tells the caller when to request a new token.

Callback Request Headers

Once a token is obtained, the callback request includes:

  • Authorization: Bearer <access_token>
  • x-optum-tenant-id: <your-tenant-id>
  • x-optum-correlation-id: <correlation-id> when the originating request included one
  • x-optum-subtenant-id: <subtenant-id> when the originating transaction included x-optum-subtenant-id

Subtenant echo behavior:

  • if the originating transaction included x-optum-subtenant-id, the callback request will include that same x-optum-subtenant-id
  • if the originating transaction did not include x-optum-subtenant-id, the callback request will not include it

Validation guidance:

  • validate the bearer token before accepting the payload
  • validate x-optum-tenant-id against the expected tenant for that callback endpoint
  • when your implementation uses subtenants, validate and store x-optum-subtenant-id as part of the callback’s routing context

What Your Callback Endpoint Must Return

  • Return 204 No Content when the callback was accepted and processed successfully.
  • Return 401 Unauthorized if the bearer token is invalid or expired.
  • Make the endpoint idempotent because retries may deliver the same payload more than once.

Polling Flow

Polling is supported whether or not you also use callbacks.

When Polling Is Useful

  • you do not want to expose a callback endpoint
  • you want a fallback when callbacks are temporarily unavailable
  • you want to inspect the task record before or after callback delivery

How To Poll

  1. Capture the discovery task id from either:
    • the Real-Time Eligibility response link header
    • the direct Coverage Discovery response location header
  2. Call:

GET /rcm/eligibility/v1/coverage-discovery/{id}

  1. Continue polling until the root status is no longer pending

Polling returns the same CoverageDiscoveryTask model that callback delivery uses, so your application logic can be shared between both retrieval methods.

If you do not have the task id immediately available, you can also search discovery records using the list endpoint and your original correlationId, then retrieve the matching task by id.

Callback Payload Interpretation Guide

Use this reading order when a callback arrives:

  1. Validate auth headers and tenant context
  2. Read root id
  3. Read root correlationId
  4. Read root status
  5. Check whether realTime is present and whether you need the related real-time eligibility context
  6. Inspect discoveryPaths.successful
  7. Inspect discoveryPaths.unsuccessful
  8. Read each nested child transaction.status
  9. Inspect discoveryPaths.pending
  10. Inspect discoveryPaths.skipped

For many customers, the most important business outcomes are:

  • Was any alternate coverage found?
  • If no coverage was found, which paths were attempted?
  • Was the parent real-time result included?
  • Which child path transactions should be retained for audit or support?
  • Did any returned statuses require follow-up under your operational workflow?

Refer to the Coverage Discovery model here for the full schema and example responses.

📘

Note: We recommend downloading the OpenAPI specification and viewing it in an OpenAPI editor for the best experience. Download the spec here.

Retries

Automated Retries

Our system automatically performs exponential‑backoff retries whenever either the token request or callback delivery fails. Operations are retried up to 5 times, with increasing delays to accommodate transient outages and reduce downstream load.

RetryMinutes
15
230
3120 (2 hours)
4300 (5 hours)
5480 (8 hours)

This prevents temporary issues (network delays, downstream downtime, intermittent service failures) from causing lost callbacks.

Ensure your callback API is idempotent, as retries may deliver the same payload more than once.

Manual Retries

We also support manual callback redrives:

  • Retry a single record using its correlationId
  • Retry by time range for bulk recovery
  • Full queue redrive for all persisted failed messages (retained up to 14 days)

These tools give operations teams full control over recovery during outages or deployment issues.

Callback Testing

Use your preferred HTTP client or API tool to test your token endpoint and callback endpoint. This guide is the source of truth for callback headers, OAuth requirements, and CoverageDiscoveryTask payload interpretation.

Recommended tooling:

Recommended validation flow:

  1. Confirm your OAuth2 token endpoint returns 200 OK for a valid client-credentials request.
  2. Send a valid callback request to your whitelisted callback URL and confirm your endpoint returns 204 No Content.
  3. Send a callback request with an invalid bearer token and confirm your endpoint returns 401 Unauthorized.
  4. Verify that your callback implementation logs the incoming tenant, correlation, and task identifiers needed for support and audit.

Example Callback Requests

Use the examples below as copy-paste starting points when testing your callback endpoint. These examples preserve the CoverageDiscoveryTask field names used by the API model.

Standard callback example

POST /your-callback-path HTTP/1.1
Authorization: Bearer <valid_access_token>
x-optum-tenant-id: <your-tenant-id>
x-optum-correlation-id: 91d76432-ac2b-4ae2-b031-f8a6615a2df4
Content-Type: application/json

{
  "id": "cd1505db-3cdf-4361-b515-52f86cd52a4c",
  "status": "success",
  "tenantName": "Customer Name",
  "traceId": "4c22f47b-1cca-7f48-373c-af7d887443b0",
  "correlationId": "91d76432-ac2b-4ae2-b031-f8a6615a2df4",
  "name": "serial discover task",
  "type": "serial",
  "startDateTime": "2024-07-22T16:17:08Z",
  "endDateTime": "2024-07-22T16:17:09Z",
  "realTime": {},
  "discoveryPaths": {
    "pending": [],
    "skipped": [],
    "successful": [
      {
        "id": "239da46d-4c63-4365-a440-9f316bb0a069",
        "name": "Commercial",
        "timestamp": "2024-07-22T16:17:08Z",
        "transaction": {
          "id": "611c1f2c-4b0a-49df-918b-5d40c8d41fc9",
          "chcPayerId": "AETNA",
          "status": "eligible",
          "x12-271": "ISA*...*271~"
        }
      }
    ],
    "unsuccessful": []
  }
}

Consolidated callback example with realTime

POST /your-callback-path HTTP/1.1
Authorization: Bearer <valid_access_token>
x-optum-tenant-id: <your-tenant-id>
x-optum-correlation-id: 91d76432-ac2b-4ae2-b031-f8a6615a2df4
Content-Type: application/json

{
  "id": "cd1505db-3cdf-4361-b515-52f86cd52a4c",
  "status": "success",
  "tenantName": "Customer Name",
  "traceId": "4c22f47b-1cca-7f48-373c-af7d887443b0",
  "correlationId": "91d76432-ac2b-4ae2-b031-f8a6615a2df4",
  "name": "serial discover task",
  "type": "serial",
  "startDateTime": "2024-07-22T16:17:08Z",
  "endDateTime": "2024-07-22T16:17:09Z",
  "realTime": {
    "id": "ccf9a2c8-2e36-4c93-b0ec-743859e569cc",
    "name": "Real Time",
    "timestamp": "2024-07-22T16:17:08Z",
    "transaction": {
      "id": "611c1f2c-4b0a-49df-918b-5d40c8d41fc9",
      "chcPayerId": "AETNA",
      "status": "patient_unknown",
      "x12-271": "ISA*...*271~"
    }
  },
  "discoveryPaths": {
    "pending": [],
    "skipped": [
      {
        "id": "",
        "name": "Commercial",
        "reason": "request does not meet path conditions",
        "timestamp": "2024-07-22T17:05:59Z"
      }
    ],
    "successful": [
      {
        "id": "18f36e9e-458b-417d-8222-6c57fdecf935",
        "name": "Medicare",
        "timestamp": "2024-07-22T17:05:58Z",
        "transaction": {
          "id": "5d26c880-aa58-4e8d-9f5a-d20e1369145d",
          "chcPayerId": "CMSHSP",
          "status": "eligible",
          "x12-271": "ISA*...*271~"
        }
      }
    ],
    "unsuccessful": []
  }
}

Invalid-token test example

POST /your-callback-path HTTP/1.1
Authorization: Bearer INVALID_BEARER_TOKEN
x-optum-tenant-id: <your-tenant-id>
x-optum-correlation-id: 91d76432-ac2b-4ae2-b031-f8a6615a2df4
Content-Type: application/json

{
  "id": "cb27966f-f2fc-4c53-936f-b5f6d6278069",
  "status": "failure",
  "tenantName": "Customer Name",
  "traceId": "4c22f47b-1cca-7f48-373c-af7d887443b0",
  "correlationId": "91d76432-ac2b-4ae2-b031-f8a6615a2df4",
  "name": "serial discover task",
  "type": "serial",
  "startDateTime": "2024-07-22T17:05:40Z",
  "endDateTime": "2024-07-22T17:05:41Z",
  "discoveryPaths": {
    "pending": [],
    "skipped": [],
    "successful": [],
    "unsuccessful": [
      {
        "id": "aa3711a8-a5c5-4ab9-8f3a-07a58706e1aa",
        "name": "Medicare",
        "timestamp": "2024-07-22T17:05:40Z",
        "transaction": {
          "id": "23ab8447-0779-40ce-8171-2771015d9e46",
          "chcPayerId": "CMSHSP",
          "status": "processing_error"
        }
      }
    ]
  }
}

When testing callback payloads:

  • use the payload shapes documented earlier in this guide
  • preserve the CoverageDiscoveryTask field names exactly as they appear in the API model
  • test both standard callback payloads and consolidated callback payloads when realTime is part of your enrolled workflow
  • test optional x-optum-subtenant-id handling only when your integration uses subtenants

📞

Need help? See Troubleshooting and Support

↪️

Looking for the homepage? Return to Enhanced Eligibility Overview here.