Search & Establish Data Connections
Application APIs
This workflow demonstrates how to search for healthcare providers, practices, and insurance companies, then establish secure data connections to retrieve patient health records. You'll use the SearchHealthResources query to find available data sources by keyword (such as "Sandbox Health System" or "Dr. Smith"), then initiate an OAuth connection flow to grant access to the user's health data from that source.
Prerequisites
- health.network - This workflow requires health.network to be enabled for access to b.well's Patient Access API connections.
- End-User Authentication - User must be authenticated with the health.network scope
- Account Creation and Consent - User account and consent must be completed
Environment URL:
- Client-Sandbox:
https://api.client-sandbox.icanbwell.com/v1/graphql
Workflow Steps
Step 1: Search for Healthcare Resources by Keyword
Use the SearchHealthResources GraphQL query to search for healthcare providers, practices, or insurance companies by keyword, location, or other criteria. The query returns connection endpoint details needed to establish data access.
Common search patterns:
- By keyword: Search for "Sandbox Health", "West Coast Health Clinic", or "UnitedHealthcare"
- By location: Filter results by geographic coordinates or zip code
- By type: Limit results to practices, individual practitioners, or insurance companies
Example GraphQL Query:
query SearchHealthResources($searchInput: SearchHealthResourcesInput) {
searchHealthResources(searchInput: $searchInput) {
pagingInfo {
pageNumber
pageSize
totalItems
totalPages
}
results {
type
id
content
logoUrl
location {
name
address {
line
city
state
postalCode
country
}
position {
latitude
longitude
}
distanceInMiles
}
organization {
name
logoUrl
endpoint {
name
status
}
}
partOf {
id
content
endpointName
logoUrl
}
npi
gender
endpoint {
name
status
}
}
}
}Example Variables:
This example searches for "Sandbox Health" near Sacramento, CA, filtering for practices, practitioners, and insurance companies with available data connections.
{
"searchInput": {
"search": "sandbox health",
"searchLocation": {
"lat": 38.5712412,
"lon": -121.4802025,
"zipCode": 10011
},
"filters": {
"includePopulatedProaOnly": true,
"type": [
"PRACTICE",
"PRACTITIONER",
"INSURANCE"
]
},
"orderBy": [
{
"field": "RELEVANCE",
"order": "DESC"
}
],
"paging": {
"pageNumber": 0,
"pageSize": 15
},
"client": [
{
"dataSets": [
"CONNECTHUB",
"NPPES"
],
"config": "client_config"
}
]
}
}Key Parameters:
search: Keyword to search for (provider name, practice name, insurance company)searchLocation: Geographic filtering by latitude/longitude or zip code (preference given to lat/lon if both provided)filters.type: Resource types to include (PRACTICE, PRACTITIONER, INSURANCE)filters.includePopulatedProaOnly: Only return results with active data connection endpointspaging: Control result paginationlogoUrl: Optional. Add to your selection set to receive organization logo images. See Step 4: Display Organization Logos
Step 2: Check Endpoint Connections
Before initiating a connection, check the endpoint.status field to determine whether the connection is currently available. This field indicates the operational health of the data connection and helps your application provide appropriate messaging to users. It is updated nightly based on percent connect success by end point.
Endpoint Status Values
| Status | Meaning | Recommended Client Behavior |
|---|---|---|
active | Healthy : Connection is working normally | Proceed with connection flow |
error | Unstable : Connection is unreliable; may or may not succeed | Can show warning (e.g., "This connection is currently experiencing issues. You can try, but it may not work.") Can allow the user to attempt. |
suspended | Under maintenance : Connection is temporarily unavailable | Can show a message (e.g., "This connection is under maintenance. Please try again later.") Block or hide the connection option. |
test | Coming soon : Connection is planned but not yet live | Can show a message (e.g., "This connection is coming soon.") or can block/hide the connection option |
Note: Endpoints with status off (deactivated) will not appear in search results at all.
Step 3: Extract Connection Endpoint Details
From the SearchHealthResources response, extract the endpoint.name value which serves as the connectionId for initiating the OAuth connection flow.
Scenario 1: Endpoint in Main Result
If the result includes an endpoint array at the top level, extract the endpoint.name directly.
Example Response:
{
"type": "PRACTICE",
"content": "Johns Hopkins Medicine",
"location": [
{
"name": "Johns Hopkins Medicine",
"address": {
"line": [
"1650 Orleans St"
],
"city": "Baltimore",
"state": "MD",
"postalCode": "21287"
}
}
],
"partOf": null,
"endpoint": [
{
"name": "example_endpoint_name",
"status": "active"
}
]
}In this example, extract "example_endpoint_name" from endpoint[].name to use as the connectionId.
The status: "active" confirms this connection is healthy and available.
Scenario 2: Endpoint in Organization Array
If the main result does not include an endpoint, check the organization array. Organizations may contain their own endpoint.name values.
{
"data": {
"searchHealthResources": {
"results": [
{
"type": "PRACTITIONER",
"content": "STEVEN ROEY",
"location": [
{
"name": "701 E. EL CAMINO REAL",
"address": {
"line": [
"701 E. EL CAMINO REAL"
],
"city": "MOUNTAIN VIEW",
"state": "CA",
"postalCode": "94040"
}
}
],
"organization": [
{
"name": "Cerner Soarian Sandbox",
"endpoint": [
{
"name": "cerner_soarian_sandbox",
"status": "active"
}
]
},
{
"name": "BWell PROA Demo",
"endpoint": [
{
"name": "proa_demo",
"status": "error"
}
]
},
{
"name": "Epic on FHIR Sandbox",
"endpoint": [
{
"name": "epic_on_fhir_sandbox",
"status": "active"
}
]
}
],
"npi": [
"1982709093"
],
"endpoint": []
}
]
}
}
}In this example:
- "cerner_soarian_sandbox" (
status: "active"); healthy, available for connection. - "proa_demo" (
status: "error"); unstable, connection may not succeed; show warning to user. - "epic_on_fhir_sandbox" (
status: "active"); healthy, available for connection.
Extract any endpoint with status: "active" from endpoint[].name within the organization[] array to use as the connectionId. For endpoints with status: "error", we can inform the user that the connection is currently unstable.
Scenario 3: Endpoint in partOf Array
If the result is of type PRACTICE and includes a populated partOf array, the endpoint may be referenced through the parent organization relationship. Results with partOf set to null represent parent organizations, while results with a populated partOf array are child entities (such as individual clinic locations) that inherit their data connection from the parent.
{
"type": "PRACTICE",
"content": "Johns Hopkins Hospital",
"location": [
{
"name": "Johns Hopkins Hospital",
"address": {
"line": [
"600 N Wolfe St"
],
"city": "Baltimore",
"state": "MD",
"postalCode": "21287"
}
}
],
"partOf": {
"id": "8d56a14d-65ee-59f6-ba83-90c96ad681e4",
"content": "Johns Hopkins Medicine",
"endpointName": "example_endpoint_name"
},
"endpoint": [
{
"name": "example_endpoint_name",
"status": "active"
}
]
}In this example, extract "example_endpoint_name" from either partOf[].endpointName or endpoint[].name to use as the connectionId. The status: "active" on the endpoint confirms the inherited parent connection is healthy.
Since all child organizations share the same endpoint as their parent organization, you can use the values within the partOf array to group related results together in your UI. This allows you to display a single parent organization (e.g. "Johns Hopkins Medicine") with nested child results underneath, improving the user experience by reducing duplicate endpoint entries and providing organizational context.
Note: If a parent endpoint has status: "error" or status: "suspended", all child organizations inheriting that endpoint are equally affected. The status on the endpoint reflects the health for all organizations using that connection.
Step 4 (Optional): Display Organization Logos
Now that you know which endpoint each result connects to, you can also show users a logo so they can confirm they are choosing the right health system before they begin the OAuth flow. If your UI does not display logos, skip this step. The connection flow works the same either way.
logoUrl is a nullable String containing a public URL to the logo image. It is additive and opt-in. You receive it only if you add it to your selection set. Existing queries that do not request it are unaffected.
Where logoUrl appears
logoUrl appearssearchHealthResources can return logoUrl at three levels, mirroring the endpoint scenarios in Step 3. Which one is populated depends on the result's type.
| Field path | Populated for | Notes |
|---|---|---|
results[].logoUrl | Any result type | The organization's own logo |
results[].organization[].logoUrl | PRACTITIONER only | Logos of affiliated health systems. Always empty for PRACTICE, INSURANCE, LABORATORY, and PHARMACY |
results[].partOf.logoUrl | PRACTICE only | The parent organization's logo. Always null for practitioner results |
Requesting all three is safe. Whichever does not apply to a given result simply returns empty or null.
The field name is always camelCase: logoUrl, not logo_url.
Example Query
query SearchHealthResourcesWithLogo($searchInput: SearchHealthResourcesInput) {
searchHealthResources(searchInput: $searchInput) {
results {
type
content
logoUrl
organization {
name
logoUrl
}
partOf {
id
content
endpointName
logoUrl
}
}
}
}Example Response
A PRACTITIONER result with a populated organization and no partOf, followed by two PRACTICE results where organization is always empty but partOf may be populated:
{
"data": {
"searchHealthResources": {
"results": [
{
"type": "PRACTITIONER",
"content": "Dr. Jane Smith, MD",
"logoUrl": null,
"organization": [
{
"name": "Example Healthcare",
"logoUrl": "https://cdn.example.com/logos/example_healthcare.png"
}
],
"partOf": null
},
{
"type": "PRACTICE",
"content": "EXAMPLE HEALTHCARE",
"logoUrl": "https://cdn.example.com/logos/example_healthcare_clinic.png",
"organization": [],
"partOf": {
"id": "c86f9970-bdcd-5a3d-a8b7-88dc282f5fd3",
"content": "Example Healthcare Inc",
"endpointName": "example_healthcare",
"logoUrl": "https://cdn.example.com/logos/example_healthcare.png"
}
},
{
"type": "PRACTICE",
"content": "Example Healthcare Inc",
"logoUrl": null,
"organization": [],
"partOf": null
}
]
}
}
}The second result shows the case worth handling explicitly: a practice whose own logoUrl is populated and whose parent carries a different logo. The third shows a practice with neither.
Choosing Which Logo to Display
Prefer the most specific logo available, then fall back:
results[].logoUrlis the result's own logo.- For
PRACTICEresults,results[].partOf.logoUrlis the parent organization's logo. - For
PRACTITIONERresults,results[].organization[0].logoUrlis an affiliated organization's logo. - Your own local placeholder.
Because child organizations inherit their endpoint from a parent (see Step 3, Scenario 3), the parent's logo is usually the right visual anchor when you group child results under a parent in your UI.
The null contractWhen an organization has no logo on file,
logoUrlis returned asnull.Treat the field as optional in your data model, check for
nullbefore use, and ship your own placeholder image like a generic building icon or an initial-based avatar to render in its place.
Fetching the Image
- No authentication. The URL is public. Fetch it with a standard image request and do not attach your API credentials, bearer token, or any custom headers.
With an endpoint name (and, if you chose to, a logo) for each result, your user can pick a connection. Next, use the selected endpoint.name to request the OAuth authorization URL.
Step 5: Retrieve OAuth Authorization URL
Before calling getOauthUrl, verify that the endpoint's status is "active" (or "error" if you choose to allow unstable connection attempts with a user warning). Do not initiate OAuth for endpoints with status: "suspended" or "test".
Using the endpoint.name extracted in Step 3 as the connectionId, query getOauthUrl to retrieve the OAuth authorization URL for the selected healthcare provider.
query getOauthUrl($connectionId: String!) {
getOauthUrl(connectionId: $connectionId) {
redirectUrl
}
}Example Variables:
{
"connectionId": "proa_demo"
}Example Response:
{
"data": {
"getOauthUrl": {
"redirectUrl": "https://auth.provider.com/oauth/authorize?client_id=..."
}
}
}Step 6: Launch Authentication Flow
Direct the user to the redirectUrl returned by getOauthUrl. This URL initiates the OAuth authentication flow where the user securely logs into their healthcare provider's portal and authorizes b.well to access their health records.
Once the user completes the OAuth flow, they will be redirected back to your application. See the OAuth Connection Flow Guide for detailed implementation options for handling OAuth completion, including postMessage listeners, URL polling, and custom redirect URLs.
Endpoint Status Reference
endpoint.status | Connection Health | User Can Attempt? | Recommended UX |
|---|---|---|---|
active | Healthy | ✅ Yes | Can show normally, proceed to OAuth |
error | Unstable | ⚠️ Yes, with warning | Can show with warning badge/message |
suspended | Under maintenance | ❌ No | Can show as unavailable or hide |
test | Coming soon | ❌ No | Can show as "coming soon" or hide |
off | Deactivated | - | Will not appear in results |
Example: Handling Mixed Status in UI
When search results contain endpoints with different statuses, your application should handle them appropriately:
{
"type": "PRACTITIONER",
"content": "DR. JANE SMITH",
"organization": [
{
"name": "Regional Medical Center",
"endpoint": [
{
"name": "regional_medical_center",
"status": "active"
}
]
},
{
"name": "Community Health Partners",
"endpoint": [
{
"name": "community_health_partners",
"status": "error"
}
]
},
{
"name": "New City Hospital",
"endpoint": [
{
"name": "new_city_hospital",
"status": "test"
}
]
}
],
"endpoint": []
}Recommended rendering:
- Regional Medical Center, Can show as available/healthy connection
- Community Health Partners, Can show with warning: "This connection is currently experiencing issues"
- New City Hospital, Can show as "Coming Soon".
Updated 10 days ago
