Search for patient records

Last updated: Dec 17, 2024
IMPLEMENTATION
HEALTH TECH VENDOR

To search for patient records, you first need to identify organizations that have seen your patient. Then you can request patient documents from each of those organizations.

Workflow for finding patient records
Workflow for finding patient records

If you want to know where you can get patient records from, explore a list of active Carequality participants.

You can also check out test patient data for context on the code examples we provide or for your own testing.

You have two options for finding a patient’s record: 

  1. Perform a broad patient search: If you don’t know where the patient is located or if the patient exists in multiple locations, Redox can provide a list of possibilities with our record locator service. This type of search is supported with the Redox Data Model API. It's the most common option since it allows you to identify all of the organizations where a patient’s record may exist.
  2. Perform a narrow patient search: There are two ways to perform a narrow search, depending on whether you have the facility code(s). This type of search is supported with either the Redox Data Model API or the Redox FHIR® API.
    1. If you have a static list of locations you wish to search or know exactly which organizations have records for the patient, you can search those specific organizations or locations directly. For this option, you must already know the facility code(s). Also, keep in mind that you can only search one organization at a time.
    2. If you don't know where the patient's records exist, you could search for relevant organizations first. You could use parameters like ZIP code or radius around the patient's address to find a list of options. The response returns a list of matching organization(s) with their facility code(s). Then, you can perform a patient search like in the first option.

Regardless of the patient search option you use, each query contains required metadata fields that identify the requesting user and their organization, specify the purpose of use, and direct the request to the target organization. These fields exist within the Meta section of the query.

Destination IDs

You must populate any test requests with the appropriate destination ID in the Meta.Destinations array based on the environment and type of requests:

Request purposeDevelopment IDProduction ID
Perform a broad patient searchadf917b5-1496-4241-87e2-ed20434b1fdb97f2dc1d-c71b-43a7-a436-9b789d44c804
Perform a patient search within a specific organization1ca254a8-8d42-4593-abb4-b21399d9de576391b961-55ae-430b-a789-cf575f03fca0
Query for/create/update/delete an organizationa07afe3b-d247-4415-827f-6837707e1b8b5d0fd248-6c52-4ad9-b907-ae10bf2dcc39
Search for a clinical summary/documentec745338-8849-43ad-a7ce-4bc5bf1d8b89628cbf79-1156-4923-b9d0-285906160ed6
Save patient details and documents to your repositoryThis is specific to your org. Redox provides the correct ID.This is specific to your org. Redox provides the correct ID.

This popular option relies on Redox's record locator service to do the heavy lifting for you. Record locator service looks for your patient's record at Carequality participant facilities within the same areas as your organization and the patient's home address (if supplied). Record locator service also leverages results from other Redox client searches so we can go beyond the search area, if possible. 

  1. If you already have the network patient ID, you can skip to step 3. If you don't have the network patient ID, using Postman or curl, send a PatientSearch.Query request with the patient's demographics to the Redox gateway (2.16.840.1.113883.3.6147.458.2).
    Example: Search for a patient
    bash
    1
    curl \
    2
    -X POST https://api.redoxengine.com/endpoint \
    3
    -H "Content-Type: application/json" \
    4
    -H "Authorization: Bearer {{access token}}" \
    5
    -d '{
    6
    "Meta": {
    7
    "Extensions": {
    8
    "sender-organization-id": {
    9
    "url": "https://api.redoxengine.com/extensions/sender-organization-id",
    10
    # This should be the OID representing you as an organization. If you have multiple levels, it helps to be specific
    11
    # but you can also just use your top-level
    12
    "string": "{{organization_oid}}"
    13
    },
    14
    "user-id": {
    15
    "url": "https://api.redoxengine.com/extensions/user-id",
    16
    # This should change per query and should be a human-readable ID for the user (typically name, not an actual ID)
    17
    "string": "{{user_human_readable_id}}"
    18
    },
    19
    "user-role": {
    20
    "url": "https://api.redoxengine.com/extensions/user-role",
    21
    # Depends on the user above, this is a SNOMED CT code
    22
    # See here: https://www.hl7.org/fhir/valueset-practitioner-role.html
    23
    "coding": {
    24
    "code": "{{user_role}}",
    25
    # This is set for the default code (112247003), but if you have a different code, this should change
    26
    "display": "Medical Doctor"
    27
    }
    28
    },
    29
    "purpose-of-use": {
    30
    "url": "https://api.redoxengine.com/extensions/purpose-of-use",
    31
    # Almost ALWAYS treatment -> depends on the app purpose, but typically this is treatment
    32
    # If it wasn't, other organizations on Carequality likely wouldn't respond
    33
    # To use this, you have to participate in Carequality, which is why you also have to push data
    34
    "coding": {
    35
    "code": "TREATMENT",
    36
    "display": "Treatment"
    37
    }
    38
    }
    39
    },
    40
    "DataModel": "PatientSearch",
    41
    "EventType": "Query",
    42
    # Remove this in Production
    43
    "Test": true,
    44
    "Destinations": [
    45
    {
    46
    # This value is standard Redox Meta structure and will vary between environments
    47
    # See the Carequality FAQ for Production values -- you're all set for sandbox testing
    48
    "ID": "{{rls_query_destination}}"
    49
    }
    50
    ]
    51
    },
    52
    "Patient": {
    53
    "Demographics": {
    54
    # These will change for whatever information you have, see our API documentation for supported fields
    55
    "FirstName": "Lacy523",
    56
    "LastName": "Waelchi213",
    57
    "DOB": "2014-05-19",
    58
    "Sex": "Male",
    59
    "Address": {
    60
    "StreetAddress": "418 Rice Ranch Apt 17",
    61
    "City": "Easton",
    62
    "State": "Massachusetts"
    63
    }
    64
    }
    65
    }
    66
    }'
  2. Record locator services takes the patient's demographics and returns the network patient ID.
  3. Using Postman or curl, send a PatientSearch.LocationQuery request with the network patient ID to the record locator destination (adf917b5-1496-4241-87e2-ed20434b1fdb for staging requests; 97f2dc1d-c71b-43a7-a436-9b789d44c804 for production requests).
    Example: Search for locations
    bash
    1
    curl \
    2
    -X POST https://api.redoxengine.com/endpoint \
    3
    -H "Content-Type: application/json" \
    4
    -H "Authorization: Bearer {{access token}}" \
    5
    -d '{
    6
    "Meta": {
    7
    "Extensions": {
    8
    "sender-organization-id": {
    9
    "url": "https://api.redoxengine.com/extensions/sender-organization-id",
    10
    # This should be the OID representing you as an organization. If you have multiple levels, it helps to be specific
    11
    # but you can also just usee your top-level
    12
    "string": "{{organization_oid}}"
    13
    },
    14
    "user-id": {
    15
    "url": "https://api.redoxengine.com/extensions/user-id",
    16
    # This should change per query and should be a human-readable ID for the user (typically name, not an actual ID)
    17
    "string": "{{user_human_readable_id}}"
    18
    },
    19
    "user-role": {
    20
    "url": "https://api.redoxengine.com/extensions/user-role",
    21
    # Depends on the user above, this is a SNOMED CT code
    22
    # See here: https://www.hl7.org/fhir/valueset-practitioner-role.html
    23
    "coding": {
    24
    "code": "{{user_role}}",
    25
    # This is set for the default code (112247003), but if you have a different code, this should change
    26
    "display": "Medical Doctor"
    27
    }
    28
    },
    29
    "purpose-of-use": {
    30
    "url": "https://api.redoxengine.com/extensions/purpose-of-use",
    31
    # Almost ALWAYS treatment -> depends on the app purpose, but typically this is treatment
    32
    # If it wasn't, other organizations on Carequality likely wouldn't respond
    33
    # To use this, you have to participate in Carequality, which is why you also have to push data
    34
    "coding": {
    35
    "code": "TREATMENT",
    36
    "display": "Treatment"
    37
    }
    38
    }
    39
    },
    40
    "DataModel": "PatientSearch",
    41
    "EventType": "LocationQuery",
    42
    # Remove this in Production
    43
    "Test": true,
    44
    "Destinations": [
    45
    {
    46
    # This value is standard Redox Meta structure and will vary between environments
    47
    # See the Carequality FAQ for Production values -- you're all set for sandbox testing
    48
    "ID": "{{rls_query_destination}}"
    49
    }
    50
    ]
    51
    },
    52
    "Patient": {
    53
    "Identifiers": [
    54
    {
    55
    # These will always change based on the previous search response. This only ever expects one identifier at this time
    56
    "IDType": "2.16.840.1.113883.3.6147.458.2",
    57
    "ID": "9ab85b7b-3946-4cfa-977f-5fbc84334ac8"
    58
    }
    59
    ]
    60
    }
    61
    }'
  4. The response returns a list of locations where the patient exists—along with the patient’s localized IDs at each location, which we validate.
    Example: Successful response for location search
    json
    1
    {
    2
    "Meta": {
    3
    "DataModel": "PatientSearch",
    4
    "EventType": "LocationQuery",
    5
    "Extensions": {
    6
    "sender-organization-id": {
    7
    "url": "https://api.redoxengine.com/extensions/sender-organization-id",
    8
    "string": "2.16.840.1.113883.3.6147.458.5420.1.1.2"
    9
    },
    10
    "user-id": {
    11
    "url": "https://api.redoxengine.com/extensions/user-id",
    12
    "string": "{{user_human_readable_id}}"
    13
    },
    14
    "user-role": {
    15
    "url": "https://api.redoxengine.com/extensions/user-role",
    16
    "coding": {
    17
    "code": "112247003",
    18
    "display": "Medical Doctor"
    19
    }
    20
    },
    21
    "purpose-of-use": {
    22
    "url": "https://api.redoxengine.com/extensions/purpose-of-use",
    23
    "coding": {
    24
    "code": "TREATMENT",
    25
    "display": "Treatment"
    26
    }
    27
    },
    28
    "task-id": {
    29
    "url": "https://api.redoxengine.com/extensions/task-id",
    30
    "string": "6cd7a70d-024f-4239-898a-5a3745242948"
    31
    },
    32
    "task-status": {
    33
    "url": "https://api.redoxengine.com/extensions/task-status",
    34
    "string": "Success"
    35
    }
    36
    },
    37
    "EventDateTime": "2021-12-08T21:47:05.931Z",
    38
    "Message": {
    39
    "ID": 12672017218
    40
    },
    41
    "Source": {
    42
    "ID": "7f296bb4-83fd-498d-92f3-a76960648788"
    43
    },
    44
    "Destinations": [
    45
    {
    46
    "ID": "adf917b5-1496-4241-87e2-ed20434b1fdb",
    47
    "Name": "Outbound RLS"
    48
    }
    49
    ],
    50
    "Logs": [
    51
    {
    52
    "ID": "c7addcc6-8206-4d3d-986b-1ce0bd1002e0",
    53
    "AttemptID": "754b8cdd-3022-4fdc-8613-cdba52db4ff0"
    54
    }
    55
    ]
    56
    },
    57
    "Patients": [
    58
    {
    59
    "Identifiers": [
    60
    {
    61
    "ID": "d5a61983-5ef8-4d31-a1ce-9a92b1f098f9",
    62
    "IDType": "2.16.840.1.113883.3.6147.458.2"
    63
    }
    64
    ],
    65
    "Organization": {
    66
    "Identifiers": [
    67
    {
    68
    "ID": "2.16.840.1.113883.3.6147.458.2",
    69
    "IDType": "OID"
    70
    }
    71
    ]
    72
    }
    73
    }
    74
    ]
    75
    }

Notes about the location search response

The Meta.Extensions.task-status.string field contains a status of either Active or Success.

Status
Definition
Results
Active
The process is asynchronously collecting locations.
The Patients array populates with any partial results as they become available.
Success
The process has finished and all possible locations were found.
Any available results have been returned.
If the Patients array is empty, it means no patients were found.

The response waits up to 10 seconds to reach a Success state. If unable to reach Success in that time, the response retains an Active status. You can retry the exact request repeatedly until it reaches a Success state.

If you know exactly where a patient was seen previously, you can search for a patient at an individual organization. If you want to search multiple organizations, you must search them one at a time.

  1. If you already have an organization and its respective OID to search, you can skip to step 4. If you don’t have an OID for the organization you want to search, send the Organization.Query request. With this query, you search by ZIP code radius or organization name.
    Example: Search for organizations
    bash
    1
    curl \
    2
    -X POST https://api.redoxengine.com/endpoint \
    3
    -H "Content-Type: application/json" \
    4
    -H "Authorization: Bearer {{access token}}" \
    5
    -d '{
    6
    "Meta": {
    7
    "DataModel": "Organization",
    8
    "EventType": "Query",
    9
    "Destinations": [
    10
    {
    11
    # This value is standard Redox Meta structure and will vary between environments
    12
    # See the Carequality FAQ for Production values -- you're all set for sandbox testing
    13
    "ID": "{{organization_query_destination}}",
    14
    "Name": "Redox Carequality - Organization Directory (XML)"
    15
    }
    16
    ]
    17
    },
    18
    "Directory": "Carequality",
    19
    # For all of the below, pass null if you're not searching that style, otherwise behavior will try to search the most exact
    20
    #
    21
    # Identifier is only if you know the exact identifier of the organization, which is rare, but used for example here (finding your own org)
    22
    "Identifier": {
    23
    "ID": "{{organization_oid}}",
    24
    "IDType": "OID"
    25
    },
    26
    # There are two "SearchType"'s "exact" and "contains" - use as desired with the "Value" field the search param
    27
    "NameSearch": {
    28
    "SearchType": null,
    29
    "Value": null
    30
    },
    31
    # You can use state to look in a specific state, or use the radius search to search from a zip code
    32
    # Using both together should not be done
    33
    "State": null,
    34
    "RadiusSearch": {
    35
    "ZipCode": null,
    36
    "Radius": null
    37
    },
    38
    # This can be used to page results
    39
    "Index": null,
    40
    "Limit": 20
    41
    }'
  2. If the request is successful, you receive a synchronous Organization.QueryResponse with the relevant organization results.
    Example: Successful response for organization search
    json
    1
    {
    2
    "Meta": {
    3
    "DataModel": "Organization",
    4
    "EventType": "Query",
    5
    "Source": {
    6
    "ID": "7f296bb4-83fd-498d-92f3-a76960648788"
    7
    },
    8
    "Message": {
    9
    "ID": 12693372849
    10
    },
    11
    "Destinations": [
    12
    {
    13
    "ID": "5de9d0e0-91f6-4b89-9bfb-461a6966d93a",
    14
    "Name": "Carequality Organizational Directory"
    15
    }
    16
    ],
    17
    "Logs": [
    18
    {
    19
    "ID": "e6e74f98-ff08-4b1a-aedb-b0e53226948b",
    20
    "AttemptID": "15c2375b-fdf7-420e-ab92-29b2676981b9"
    21
    }
    22
    ]
    23
    },
    24
    "Directory": "Carequality",
    25
    "Organizations": []
    26
    }
  3. From the results list, you can select one or all of these organizations to then run a patient search.
  4. Now that you have an organization to search, send the PatientSearch.Query request with the patient's demographics to see if that organization has your patient’s records. You must use the organization’s OID in each request.
    Data model example: Search for a patient within one organization
    bash
    1
    curl \
    2
    -X POST https://api.redoxengine.com/endpoint \
    3
    -H "Content-Type: application/json" \
    4
    -H "Authorization: Bearer {{access token}}" \
    5
    -d '{
    6
    "Meta": {
    7
    "Extensions": {
    8
    "sender-organization-id": {
    9
    "url": "https://api.redoxengine.com/extensions/sender-organization-id",
    10
    # This is the OID that represents you as an organization. If you have multiple levels, it helps to be specific
    11
    # but you can also just use your top-level.
    12
    "string": "{{organization_oid}}"
    13
    },
    14
    "user-id": {
    15
    "url": "https://api.redoxengine.com/extensions/user-id",
    16
    # This should change per request and should be a human-readable ID for the user (typically name, not an actual ID).
    17
    "string": "{{user_human_readable_id}}"
    18
    },
    19
    "user-role": {
    20
    "url": "https://api.redoxengine.com/extensions/user-role",
    21
    # This is a SNOMED CT code that relates to the user above.
    22
    # See here: https://www.hl7.org/fhir/valueset-practitioner-role.html.
    23
    "coding": {
    24
    "code": "{{user_role}}",
    25
    # This is set for the default code (112247003), but this should change if you have a different code.
    26
    "display": "Medical Doctor"
    27
    }
    28
    },
    29
    "purpose-of-use": {
    30
    "url": "https://api.redoxengine.com/extensions/purpose-of-use",
    31
    # Almost ALWAYS treatment -> depends on the app purpose, but typically this is treatment.
    32
    # If it wasn't, other organizations on Carequality likely wouldn't respond.
    33
    # To use this, you have to participate in Carequality, which is why you also have to push data.
    34
    "coding": {
    35
    "code": "TREATMENT",
    36
    "display": "Treatment"
    37
    }
    38
    }
    39
    },
    40
    "DataModel": "PatientSearch",
    41
    "EventType": "Query",
    42
    # Removed in production
    43
    "Test": true,
    44
    "Destinations": [
    45
    {
    46
    # This value is standard Redox Meta structure and will vary between environments.
    47
    # See the Carequality FAQ for Production values -- you're all set for sandbox testing.
    48
    "ID": "{{standard_patient_destination}}"
    49
    }
    50
    ],
    51
    # From the previous Organization.Query, this should be the Organization's OID that you want to search.
    52
    # So if there are 4 organizations you're interested in, you must make 4 of these requests to find the patient at that location.
    53
    # However, watch out for duplicates by looking at the Endpoints values in the Organization results, to see if they have
    54
    # the same gateway.
    55
    # Below, we use Redox for example.
    56
    "FacilityCode": "2.16.840.1.113883.3.6147.458.2"
    57
    },
    58
    "Patient": {
    59
    "Demographics": {
    60
    # Populate these fields based on your patient's information. See our API documentation for supported fields.
    61
    "FirstName": "Adolfo",
    62
    "LastName": "Kessler",
    63
    "DOB": "2002-10-31",
    64
    "SSN": "999-55-2115",
    65
    "Sex": "Male",
    66
    "Address": {
    67
    "City": "Madison",
    68
    "State": "Wisconsin",
    69
    "ZIP": "53711"
    70
    }
    71
    }
    72
    }
    73
    }
    FHIR example: Search for a patient within one organization
    bash
    1
    curl --location --request POST 'https://api.redoxengine.com/fhir/R4/ceq-xcpd:2.16.840.1.113883.3.6147.458.2/Development/Patient/_search' \
    2
    --header 'Authorization: Bearer <TOKEN>' \
    3
    --header 'x-sender-organization-id: {{your_oid}}' \
    4
    --header 'x-user-id: {{user_human_readable_id}}' \
    5
    --header 'x-user-role: {{user_role}}' \
    6
    --header 'x-purpose-of-use: TREATMENT' \
    7
    --header 'redox-source-id: {{your_source_id_if_multiple}}' \
    8
    --header 'Content-Type: application/x-www-form-urlencoded' \
    9
    --data-urlencode 'given=Pauline' \
    10
    --data-urlencode 'family=Bixby' \
    11
    --data-urlencode 'birthdate=19980601' \
    12
    --data-urlencode 'identifier=http://hl7.org/fhir/sid/us-ssn|010-10-1000' \
    13
    --data-urlencode 'gender=Female'
  5. If your search matches a patient at the given organization, the response returns the patient’s identifier and additional details.
    Data model example: Successful response for a patient search within one organization
    json
    1
    {
    2
    "Patient": {
    3
    "Demographics": {
    4
    "Address": {
    5
    "County": null,
    6
    "Country": null,
    7
    "ZIP": "53711",
    8
    "State": "wisconsin",
    9
    "City": "madison",
    10
    "StreetAddress": "602 schiller junction suite 68"
    11
    },
    12
    "EmailAddresses": [],
    13
    "PhoneNumber": {
    14
    "Work": null,
    15
    "Mobile": "+15556533376",
    16
    "Home": "+15556533376"
    17
    },
    18
    "Sex": null,
    19
    "DOB": "2002-10-31",
    20
    "LastName": "kessler",
    21
    "FirstName": "adolfo",
    22
    "SSN": ""
    23
    },
    24
    "Identifiers": [
    25
    {
    26
    "IDType": "2.16.840.1.113883.3.6147.458.2",
    27
    "ID": "45e5fadd-0496-4e48-be26-a06d78f8e950"
    28
    }
    29
    ]
    30
    },
    31
    "Meta": {
    32
    "DataModel": "PatientSearch",
    33
    "EventType": "Query",
    34
    "Message": {
    35
    "ID": 12721022314
    36
    },
    37
    "Source": {
    38
    "ID": "d9c19117-7778-47fd-9f55-b3bccc4055f8"
    39
    },
    40
    "Destinations": [
    41
    {
    42
    "ID": "1ca254a8-8d42-4593-abb4-b21399d9de57",
    43
    "Name": "Carequality Sandbox - XCPD"
    44
    }
    45
    ],
    46
    "Logs": [
    47
    {
    48
    "ID": "0a4eb252-cb7a-4349-b0a5-5ccc53be2e37",
    49
    "AttemptID": "95f2c3bd-8660-45b4-a73b-a3543908d4c2"
    50
    }
    51
    ]
    52
    }
    53
    }
    FHIR example: Successful response for a patient search within one organization
    json
    1
    {
    2
    "body": {
    3
    "resourceType": "Bundle",
    4
    "type": "searchset",
    5
    "total": 1,
    6
    "entry": [
    7
    {
    8
    "resource": [
    9
    {
    10
    "resourceType": "Patient",
    11
    "id": "681d2103-f883-4334-886b-59358580dcb1^2.16.840.1.113883.3.6147.458.2",
    12
    "identifier": [
    13
    {
    14
    "value": "681d2103-f883-4334-886b-59358580dcb1",
    15
    "system": "2.16.840.1.113883.3.6147.458.2"
    16
    }
    17
    ],
    18
    "name": [
    19
    {
    20
    "given": [
    21
    "pauline"
    22
    ],
    23
    "family": "bixby"
    24
    }
    25
    ],
    26
    "gender": "female",
    27
    "birthDate": "1998-06-01",
    28
    "telecom": [
    29
    {
    30
    "value": "18088675309",
    31
    "system": "phone",
    32
    "use": "home"
    33
    }
    34
    ],
    35
    "address": [
    36
    {
    37
    "line": [
    38
    "4762 walnut street"
    39
    ],
    40
    "city": "mt. horeb",
    41
    "state": "WI",
    42
    "postalCode": 53572
    43
    }
    44
    ]
    45
    }
    46
    ],
    47
    "search": {
    48
    "mode": "match"
    49
    }
    50
    }
    51
    ]
    52
    }
    53
    }
    If a patient isn’t found, the response returns an empty array.
  6. Repeat steps 4 and 5 for every organization you want to search.

Next steps