Operation: $match
Overview
The $match endpoint allows you to find similar or matching concepts across different repositories in OCL. While search returns concepts that match a specific search query, $match returns concept candidates that match structured input data, such as a row in a spreadsheet. This could be used to retrieve mapping candidates for an entire spreadsheet.
$match API must accept POST (GET is not supported).
Authentication & Access
Authentication required. The user must be signed in.
The user must be mapper-approved and not on the mapper waitlist. Returns
403 Forbiddenotherwise.Plan-based throttling is applied per user.
Row Indexing
For every request, the API automatically adds a zero-based __index field to each row in the response. This acts as a local identifier to correlate each response item with the corresponding input item. The __index is always returned and starts at 0.
Batching & Concurrency
The API processes rows in batches. The client interface allows you to set the batch size, which is useful for APIs with longer computation times—using a lower batch size helps avoid timeouts. By default, the UI sends two concurrent batch requests at a time. For example, with 1000 rows and a batch size of 50, two batches (each with 50 rows) are sent concurrently; as soon as one finishes, the next batch is sent, maintaining exactly two in-flight requests.
$match Algorithm Fields
id- Exact match onconcept.idin the target repositoryname- Keyword or semantic search on concept primary display namesynonyms- Keyword or semantic search on all concept names and synonymsdescription- String search on all concept descriptionsProperties: String match on concept properties
Syntax:
property:<property-name>where<property-name>corresponds withrepo.properties.codeNote: A property must also be defined as a filter (i.e.
repo.filters) in order for it to be indexed and searchableThere are two special cases - for historical compatibility, class and datatype are stored as core concept attributes:
property:class- String match onconcept.concept_classproperty:datatype- String match onconcept.datatype
Examples:
property:component- String match on LOINC’s “component” propertyproperty:units- String match on a “units” property
mapping:code- Matches concepts in the target repo that share a mapping with the input row. For example, the input row and target concept share a mapping to the same LOINC code.mapping:list- Matches concepts in the target repo that share a mapping, where the input is a list of mappings for the row.
Request
POST /concepts/$match/
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
verbose |
Boolean | No | false |
More details in results (full concept details) |
brief |
Boolean | No | false |
Return minimal concept fields in results |
limit |
Integer | No | 1 |
Number of results to be returned per row (page size) |
offset |
Integer | No | 0 |
Number of results to skip |
page |
Integer | No | 1 |
Page number for paginated results |
includeRetired |
Boolean | No | false |
Match against retired concepts as well |
bestMatch |
Boolean | No | false |
Forces a minimum search score threshold to be applied, filtering out low-quality matches |
semantic |
Boolean | No | false |
Use semantic (LM-based) matching algorithm. The target repository must have the semantic match algorithm enabled. |
numCandidates |
Integer | No | 3000 |
Only needed when semantic=true. Number of approximate nearest neighbor candidates. Range: 1 to 3000. For more information: https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html#tune-approximate-knn-for-speed-accuracy |
kNearest |
Integer | No | 100 |
Only needed when semantic=true. Number of nearest neighbors to return from vector search. Range: 1 to 100. |
encoder_model |
String | No | (none) | Custom encoder model name for semantic vector search |
reranker |
Boolean | No | false |
Enable cross-encoder reranking of results. Only applicable when semantic=true. |
Request Body Schema
| Code (Name) | Card. | Type | Definition (Description) |
|---|---|---|---|
target_repo_url |
0..1 | string | Repository URL to match against. Uses $resolve to identify the specific repo version. Either target_repo_url or target_repo must be provided. Example: /orgs/CIEL/sources/CIEL/ |
target_repo |
0..1 | object | Alternative to target_repo_url. Object with owner, source, source_version, and owner_type fields. Either target_repo_url or target_repo must be provided. |
rows |
1..* | list | List of concept-like key-value pairs; each row may have different fields. Only fields that are recognized by the matching algorithm are used, all other fields are ignored. Example: [{"s_n":"1","name":"malaria"},{"s_n":"2","name":"blood type"}] |
rows.id |
0..1 | string | Exact match against a concept ID. (May be removed in future versions.) Example Input Data: 12, 57, A01.1 |
rows.name |
0..1 | string | Semantic or fuzzy search on primary display name. Example Input Data: Anemia due to blood loss |
rows.synonyms |
0..1 | string or list | Semantic or fuzzy search across all names/synonyms. Accepts a single string or a list of strings. Example Input Data: "Anemia, blood loss" or ["Anemia, blood loss", "Anémie secondaire à une hémorragie"] |
rows.description |
0..1 | string | Text search on concept descriptions. Example Input Data: "Anemia due to bleeding or a hemorrhagic process" |
rows.concept_class |
0..1 | string | Match on concept class (e.g., diagnosis, symptom). Example Input Data: Diagnosis, Symptom |
rows.datatype |
0..1 | string | Match on datatype (e.g., numeric, coded). Example Input Data: Numeric, Coded |
rows.mapping_code |
0..1 | string | Exact match on a concept ID or mapping in the target repo version. Example Input Data: D50.0, Z87.5, X59.9 |
rows.mapping_list |
0..1 | string | Exact match on comma-separated mapping list. (In development.) Example Input Data: CIEL:1858, ICD10:DC14.Z, LOINC:5792-7 |
rows.same_as_map_codes |
0..1 | string | Search only "same as" mappings. (Deprecated.) Example Input Data: CIEL:1858, ICD10:DC14.Z, LOINC:5792-7 |
rows.other_map_codes |
0..1 | string | Search all non-"same as" mappings. (Deprecated.) Example Input Data: CIEL:1858, ICD10:DC14.Z, LOINC:5792-7 |
filter |
0..1 | object | Filtering criteria. Supports locale (string, comma-separated locale codes for semantic search) and faceted filters matching the target repository's filter definitions. |
map_config |
0..* | list | Optional list configuring mapping logic per row. Example from Request Body: see below. |
map_config.type |
1..1 | code | Type of mapping: mapping-code or mapping-list. Example: mapping-code, mapping-list |
map_config.input_column |
1..1 | string | Name of the row-field to use. Example: loinc-example, icd10-example, list example |
map_config.target_source_url |
0..1 | string | Target repo URL for mapping-code entries (required if type is mapping-code). Example: /orgs/CIEL/sources/CIEL/ |
map_config.separator |
0..1 | string | Separator between source name and code in mapping-list. Example: : |
map_config.delimiter |
0..1 | string | Delimiter for multiple mappings in mapping-list. Example: , |
map_config.target_urls |
0..1 | map | URL map of source mnemonics to repositories. Required for mapping-list. Example: {"ICD10": "/orgs/WHO/sources/ICD-10-WHO/", "CIEL": "/orgs/CIEL/sources/CIEL/", "LOINC": "/orgs/Regenstrief/sources/LOINC/"} |
Response Format
| Code (Name) | Card. | Type | Definition (Description) |
|---|---|---|---|
| \<base> | 1 | list | A list of response objects, one per input row |
| row | 1 | map | The original row submitted, plus an auto-added zero-based __index local identifier |
| results | 1..* | list | Ordered list of concept candidates, sorted by score |
| results.url | 1 | string | Concept URL |
| results.display_name | 1 | string | Primary display name |
| results.id | 1 | string | Concept ID |
| results.retired | 0..1 | bool | Whether the concept is retired |
| results.concept_class | 0..1 | string | Concept class |
| results.datatype | 0..1 | string | Concept datatype |
| results.property | 0..* | list | Concept properties |
| results.property.code | 1 | string | The key of the property (e.g. concept_class) |
| results.property.valueCode | 0..1 | string | |
| results.property.valueCoding | 0..1 | ... | |
| results.property.valueString | 0..1 | string | |
| results.property.valueInteger | 0..1 | int | |
| results.property.valueBoolean | 0..1 | bool | |
| results.property.valueDateTime | 0..1 | DateTime | |
| results.property.valueDecimal | 0..1 | decimal | |
| results.extras | 0..1 | map | Additional concept attributes |
| results.search_meta | 1 | object | Search metadata (always included for $match) |
| results.search_meta.search_score | 1 | decimal | Raw Elasticsearch score |
| results.search_meta.search_normalized_score | 1 | decimal | Normalized score on a 0-100 scale |
| results.search_meta.search_rerank_score | 0..1 | decimal | Cross-encoder rerank score (only present when reranker=true) |
| results.search_meta.match_type | 1 | string | Match confidence: very_high, high, medium, or low (see below) |
| results.search_meta.algorithm | 1 | string | Algorithm used: ocl-search, ocl-semantic, or ocl-ciel-bridge |
| results.search_meta.search_highlight | 0..1 | map | Highlighted matching fields (e.g. name, synonyms) |
| results.search_meta.search_confidence | 0..1 | string | Confidence value (may be null) |
| results.source | 0..1 | string | Source mnemonic |
| results.owner | 0..1 | string | Owner mnemonic |
| results.owner_type | 0..1 | string | Owner type (e.g. Organization) |
| results.owner_url | 0..1 | string | Owner URL |
| results.mappings | 0..1 | list | Concept mappings (when verbose) |
| results.names | 0..1 | list | Concept names (when verbose) |
| map_config | 0..1 | list | Echo of the map_config from the request |
| filter | 0..1 | object | Echo of the filter from the request |
Match Type
The match_type field indicates the confidence level of each result. How it is determined depends on the search mode:
When limit=1: Always very_high (single best result is returned).
When limit > 1 with semantic search + reranker:
very_high- Normalized score >= 0.9high- Normalized score >= 0.65medium- Normalized score >= 0.5low- Normalized score < 0.5
When limit > 1 with semantic search (no reranker):
very_high- Name appears in highlights, or normalized score >= threshold (0.9)high- Synonyms appear in highlightsmedium- Any field appears in highlightslow- No highlights
When limit > 1 with token-based (default) search:
very_high- Name appears in highlightshigh- Synonyms appear in highlightsmedium- Any field appears in highlightslow- No highlights
When bestMatch=true, results with low match type are excluded.
Notes
search_metais always included in$matchresponses. There is no need to passincludeSearchMeta=true.CIEL bridge algorithm: When the target repo is CIEL and a
filter.target_repopoints to a non-CIEL repo, theocl-ciel-bridgealgorithm is used.Pagination via
offset/limitorpage/limitapplies to each row’s result set independently.
Example Response
[
{
"row": {"local_id": "1396", "name": "malaria"},
"results": [
{
"search_meta": {
"search_score": 18.534,
"search_normalized_score": 95.2,
"match_type": "very_high",
"algorithm": "ocl-semantic",
"search_confidence": null,
"search_highlight": {
"name": ["<em>Malaria</em>"]
}
},
"id": "116128",
"url": "/orgs/CIEL/sources/CIEL/concepts/116128/",
"retired": false,
"source": "CIEL",
"owner": "CIEL",
"owner_type": "Organization",
"owner_url": "/orgs/CIEL/",
"display_name": "Malaria",
"display_locale": "en"
}
],
"map_config": [],
"filter": {}
}
]
Example Request 1: Simple Request
POST https://api.openconceptlab.org/concepts/$match/?semantic=true&bestMatch=true&limit=1
{
"rows": [
{"local_id": "1396", "name": "malaria"},
{"local_id": "2", "name": "a1c"}
],
"target_repo_url": "/orgs/CIEL/sources/CIEL/"
}
Example Request 2: With mapping configuration
POST https://api.openconceptlab.org/concepts/$match/?limit=3
{
"rows": [
{"local_id": "1396", "name": "Mother's HIV Status", "loinc_code": "75179-2"},
{"local_id": "2", "name": "Weeks of gestation", "loinc_code": "11884-4"}
],
"target_repo_url": "/orgs/Regenstrief/sources/LOINC/2.71.21AA/",
"map_config": [
{"type": "mapping-code", "input_column": "loinc_code", "target_source_url": "/orgs/CIEL/sources/CIEL/"},
{"type": "mapping-list", "input_column": "maps", "separator": ":", "delimiter": ",", "target_urls": {
"ICD10": "/orgs/WHO/sources/ICD-10-WHO/",
"CIEL": "/orgs/CIEL/sources/CIEL/",
"LOINC": "/orgs/Regenstrief/sources/LOINC/"
}}
]
}
Example Request 3: Semantic search with reranker and locale filter
POST https://api.openconceptlab.org/concepts/$match/?semantic=true&reranker=true&limit=5
{
"rows": [
{"name": "Type 2 diabetes mellitus", "synonyms": ["Adult-onset diabetes", "Non-insulin dependent diabetes"]}
],
"target_repo_url": "/orgs/CIEL/sources/CIEL/",
"filter": {
"locale": "en,fr"
}
}