FHIR Terminology Server ECL queries

Currently migrating from own SNOWSTORM / SNOMED CT server to the NHS terminology FHIR server.

The API calls needed all work except ECL queries, e.g.:
curl --location --request GET ‘https://ontology.nhs.uk/production1/fhir/ValueSet/$expand?url=http://snomed.info/sct?fhir_vs=ecl/<<362958002’ --header ‘Authorization: Bearer AUTH_CODE_GOES_HERE’

HTTP Status 400 – Bad Request

Is there another server for ECL queries?

1 Like

Hi @david.morrison have you had a look at The NHS Digital Terminology Server information hub?

Yes I’ve scanned FHIR API documentation, but ECL seems AWOL. It is mentioned in a few NHS presentations I’ve seen.

The International SNOMED CT Browser has a " Expression Constraint Queries" tab:

But the NHS SNOMED CT Browser has no tab:

I’m guessing the NHS SNOMED CT Browser is using the NHS FHIR server, so potentially the ECL module has been omitted.

Fallback position is to continue with a standalone IHTSDO SNOWSTORM server, but this may require regular SNOMED CT updates and a reasonably powerful server.

Have you been able to use the ECL builder in Shrimp?


If so, in your browser turn on deveoper tools (on my chrome browser I can right click and then select the inspect option).

Then when you execute your ecl statement you will see the query you need to use in the network tab

I think the basic syntax of your query is correct.

It looks like I’ve used a POST instead of a GET
and also used a FHIR Parameters resource to pass in the url

Can’t tell exactly as I’ve used a code library to handle the actual call

This is the HAPI FHIR kotlin code I use.

val client = provideClient()

            val input = ParametersUtil.newInstance(ctx)
ParametersUtil.addParameterToParametersUri(ctx, input, "url", FhirSystems.SNOMED_CT+"?fhir_vs=ecl/"+ecl)
            if (count != null) {
                ParametersUtil.addParameterToParametersInteger(ctx, input, "count", count.value)
            val output: IBaseParameters =
            if (output is Parameters) {
                return output

The code I’m working with is Rails and it works against a SNOWSTORM server behind a NGINX webserver with basic authorisation, but the Rails code is not working against the NHS server :frowning:

I’m messin with CURL because I just want to use a basic tool to prove connectivity .

With minimal changes, the following worked, showing NHS server does support ECL query :slight_smile:

curl “https://ontology.nhs.uk/production1/fhir/ValueSet/\$expand?url=http://snomed.info/sct?fhir_vs=ecl/<<%20408591000” --header “Authorization: Bearer AUTH_CODE_GOES_HERE”

The changes to get is CURL example working are:
1/ Escape the ‘$’ before the expand
2/ URL encode the ECL query, e.g., the 2 characters and a space '<< ’ becomes ‘%3C%3C%20’

1 Like

NHS Terminology Server definitely has rich support for ECL. In this case the ECL expression is being passed as a URL parameter and therefore needs to be URL encoded (this is also true of any URL parameter you pass to the APIs)

There are some further examples that might be useful. You can also pass the ECL queries in a POST body (which will not need URL encoding)
ECL curl example

Happy to add more examples if it would help to make it easier to get going

For any Rails developers, below is a working Ruby Rails snippet for the NHS FHIR GET version for an ECL query.

        clean_ecl_query(query)                          # "<< 248153007  | Male | OR << 248152002  | Female | " becomes "<< 248153007 OR <<248152002" 
        token = FhirServer::get_token()                 # Handle obtaining token and token expiration 
        begin                                           # Handle endless ways to supply invalid query (access and authorisation to query field is controlled )
            url = URI(term_server_ecl_base_uri + query) # URI("https://ontology.nhs.uk/production1/fhir/ValueSet/$expand?url=http://snomed.info/sct?fhir_vs=ecl/" + query)
        rescue => e
            raise "Invalid ECL query supplied: " + e.message
        Net::HTTP.start(url.host, url.port,
            :use_ssl => url.scheme == 'https', 
            :verify_mode => OpenSSL::SSL::VERIFY_NONE) do |http|
            request = Net::HTTP::Get.new url 
            request['Authorization'] = "Bearer #{token}"
            @data = http.request request # Net::HTTPResponse object     

        @results_hash = JSON.parse @data.body

Response should be “169839008 | Baby female |”, “169838000 | Baby male |”, “248152002 | Female |”, “248153007 | Male |”

1 Like