custom search parameter
# support
l
Hi there! I'm created a
SearchParameter
to allow us to search for practitioner's by their state of licensure. it looks like this
Copy code
{
  "resourceType": "SearchParameter",
  "url": "https://--------.com/fhir/SearchParameter/practitioner-license-state",
  "name": "license-state",
  "status": "active",
  "description": "Search practitioners by state where their license is valid (USPS state codes)",
  "code": "license-state",
  "base": [
    "Practitioner"
  ],
  "type": "token",
  "expression": "Practitioner.qualification.extension.where(url='http://hl7.org/fhir/us/davinci-pdex-plan-net/StructureDefinition/practitioner-qualification').extension.where(url='whereValid').value.ofType(CodeableConcept).coding.code",
  "id": "9ec9cef7-5142-486a-aaeb-6934de1a1604",
  "meta": {
    "versionId": "a6d3f326-031e-4136-83b0-94b654201fea",
    "lastUpdated": "2026-03-05T01:39:55.758Z",
    "author": {
      "reference": "ClientApplication/--------------------",
      "display": "----Staging Default Client"
    },
    "project": "--------------------",
    "compartment": [
      {
        "reference": "Project/-------------------"
      }
    ]
  }
}
(redacted some id's) when trying to seach on that though via: https://api.medplum.com/fhir/R4/Practitioner?license-state=CA&_count=10 I get an error with "Unknown search parameter: license-state" in the response. Any idea what I might be doing wrong? thanks in advance
a
Howdy! We don't currently support custom search parameters on the client side
l
hey @Aditya Suri just to be clear, we can't use this capability and create a SearchParameter https://www.medplum.com/docs/api/fhir/resources/searchparameter?section=usage and then make REST calls with it?
a
are you self hosted?
l
no
a
On Medplum Cloud, custom
SearchParameters
aren't supported on the client side today. You can create the resource, but the server won't index against it. Your data model is solid though. That Da Vinci PDex
whereValid
extension is perfect. The workaround for making it searchable might be to use a Bot + Subscription to sync the license states into Practitioner.meta.tag. Something like: Create a
Subscription
on
Practitioner
(create + update) Bot reads
qualification[].extension[whereValid].valueCodeableConcept.coding[].code
Bot writes those state codes as
meta.tag
entries with system https://www.usps.com/ Then you can search:
GET /fhir/R4/Practitioner?_tag=https://www.usps.com/|CA&_count=10
That uses the built-in
_tag
search parameter. On our end I do think a search parameter like this is definetly something worth having so I'll go ahead and make a GH issue. We've never done search params on an extension, but its a relatively traversed path so could be valuable.
l
oh that's a really clever solution!
awesome! please post the GH ticket so I can follow
thanks a ton @Aditya Suri
a
will do haven't made it yet - bouncing between a few calls today but ill get to it!
l
thanks!
d
On the self-hosted side is there a path to using custom search parameters?
a
it requires a db migration and redeployment, on top of creating the bundle. @Doug DeBold
l
thanks!
d
@Aditya Suri I am testing this locally but it is not working. I have: 1. Added a new column to Task table via psql 2. Created the new SearchParameter 3. Restarted the server The issue is that @medplum/server caches the search parameters in-memory from @medplum/definitions, so the new column is never populated. I could fix this locally by adding my search param to
search-parameters-medplum.json
but I'm using the docker image in production and so cannot easily modify these files. Any ideas?
I have gotten this working via patching
search-parameters-medplum.json
in my entrypoint script but that feels really hacky
a
did you rebuild the docker image?
n
Separately, I’m also tracking [#8147](https://github.com/medplum/medplum/issues/8147) to better understand how self-hosting could implement custom search parameters in some cases. Any insight there would be appreciated!
d
@Aditya Suri I was really hoping to avoid this but I've taken the nuclear option of wrapping the medplum docker image with my own builder and modifying the search parameter definitions. This seems to work well enough
j
@Aditya Suri would it be possible to do something like this in
packages/server/src/fhir/repo.ts
call indexSearchParameter() to hot-reload it into the live schema or add a
loadCustomSearchParameters()
function that queries the DB for user-created SearchParameters and indexes them, called from
initAppServices()
in
packages/server/src/app.ts
and at the end of
rebuildR4SearchParameters()
in
packages/server/src/seeds/searchparameters.ts
i'm also trying to use this custom search param on a Basic fhir resource but its not recognizing it (I'm using a selfhosted instance as well)
d
The path that I took that is definitely a bit hacky is this: 1. Make a custom Dockerfile that inherits from the medplum image 2. Copy my own bundle of search params into the definitions package 3. Using sed, edit the
SEARCH_PARAMETER_BUNDLE_FILES
value in index.cjs and index.mjs to include my file 4. Build and publish the new image myself Based on my understanding of the code, all of the search params MUST but loaded into the in-memory cache for the search columns to be set on record updates.
a
On self-hosted, the server needs to know about the SearchParameter at the definitions level, and Postgres needs the corresponding column. The path is: 1. Add your SearchParameter to search-parameters-medplum.json in @medplum/definitions 2. Add the column to the appropriate lookup table via migration 3. Rebuild and deploy 4. Reindex affected resources For the Basic resource param what's the FHIRPath expression?
d
Technically I think you can use the DB drift tool to do the migration if you have properly added the custom search parameter to the definitions.
But I manually added the columns for my use case
j
I actually ended up doing something like this after seeing you previous comment but for my case, with what I was trying, I realized the Basic fhir resource isnt as flexible as I imagined (it required the column for to exist in the db) so I might have to find an alternative way
ooh when you say via migration. Is there a way documented process for this? @Aditya Suri I created issue [#8650](https://github.com/medplum/medplum/issues/8650) with an example of what i was trying to do with the basic resource
a
Want to add some important context to the thread: Modifying the definitions package and adding DB columns is technically how search params work under the hood, but the Medplum team can't support or troubleshoot instances that have gone down this path. This also diverges from what's supported on Medplum Hosted and our standard Enterprise offering, but for Enterprise customers, we can work on migrating to the supported path on a case-by-case basis. The supported approach for both Cloud and self-hosted is the Bot + Subscription pattern (syncing values into meta.tag or another natively-indexed field).
d
I'm at least fully aware that I'm going off the rails with this modification to search parameters... this is definitely a last resort for us to build out what we want but have to do it sometimes. @JT in the super config, you can use the db drift tool to see how the schema has diverged and then run a migration to fix it. This is how I automatically added the columns, but most times I simply used
psql
and added the columns and indexes following the naming patterns of the other search parameter columns
r
@Doug DeBold - what search params are you adding?
d
Right now task has
dueDate
which is basically
task.restriction.period.start ?? task.restriction.period.end
By coalescing these 2 values it makes it impossible to make certain queries. For example, if I want to show all tasks with a due date (
task.period.restriction.end
) in the future, if those tasks also have the
period.start
then you cannot filter for those future due tasks. To solve this I added 2 search parameters: 1.
customDueDate
which only looks at
task.period.restriction.end
2.
notBefore
which only looks at
task.period.restriction.start
I added the "custom" due date b/c the current search param is called due date and I didn't want to deal with overwriting it
31 Views