This reference provides documentation for MDPI ROR Entity Search API, including endpoint definitions, request and response schemas, authentication, error handling, and rate limits.
ROR Entity Search API
At a glance
Quick start
Authentication - Connecting to the API
API key access
Quotas
Endpoints Reference
POST /ror/search
POST /ror/search_topk
Reading Responses & Errors
Top-level response shape
Match object fields
Sending feedback
HTTP status codes
Getting an API key
How to request one
Using your key
The ROR Entity Search API matches free-text affiliation strings (e.g. "Dept. of Physics, MIT, Cambridge, USA") to canonical institution records from the Research Organization Registry (ROR). It returns the matched institution's name, ROR ID, country, city, and a confidence score.
Under the hood, this API is a thin, secured gateway in front of the open-source mdpi-ror-search engine, which does the actual NER + embedding-based matching. This gateway adds authentication, per-user quotas, and a stable public response format.
| Base URL | https://dev.mdpi.com/api/v1 |
| Protocol | HTTPS, JSON in and out |
| Methods | POST for search endpoints, GET for health check |
| Auth | Required for every request, see Authentication |
| Core endpoints | POST /ror/search, POST /ror/search_topk - see Endpoints |
curl -X POST "https://dev.mdpi.com/api/v1/ror/search_topk" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-api-key>" \
-d '{
"affiliations": ["Massachusetts Institute of Technology"],
"top_k": 1
}'
An API key is required for every request (see Authentication). See Getting an API Key to request one.
Every request to the API requires a registered API key. Requests without a valid key are rejected.
Send your key in the Authorization header as a bearer token:
Authorization: Bearer <your-api-key>
curl -X POST "https://dev.mdpi.com/api/v1/ror/search_topk" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-api-key>" \
-d '{"affiliations": ["ETH Zurich"], "top_k": 1}'
Requests are tracked per key, each with its own daily quota. Treat the key as a single opaque secret string, thereby never split, parse, or log it. See Getting an API Key to request one.
429 Too Many Requests with {"detail": "Request blocked, quota exceeded."}. Wait for the daily reset, or ask us to raise your key's limit.All endpoints below are relative to the base URL: https://dev.mdpi.com/api/v1.
Both search endpoints require a JSON body and return the same response shape (see Reading Responses & Errors). The only difference between them is how many matches come back per affiliation.
POST /ror/searchReturns every matching institution whose similarity score clears the internal confidence threshold, for each affiliation string you send. Use this when you want all plausible candidates rather than a fixed count.
| Field | Type | Required | Description |
|---|---|---|---|
affiliations |
string[] |
Yes | One or more affiliation strings to search. |
include_deprecated_ror_ids |
boolean |
No | If true, includes institutions whose ROR ID has since been withdrawn/superseded. Defaults to excluding them. |
curl -X POST "https://dev.mdpi.com/api/v1/ror/search" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-api-key>" \
-d '{
"affiliations": ["Massachusetts Institute of Technology"],
"include_deprecated_ror_ids": false
}'
{
"response": [
{
"raw_affiliation": "Massachusetts Institute of Technology",
"affiliation_matches": [
{
"institution_name": "Massachusetts Institute of Technology",
"institution_urls": ["https://web.mit.edu"],
"ror_id": "https://ror.org/042nb2s44",
"grid_id": "grid.116068.8",
"score": 0.98,
"country": "United States",
"country_code": "US",
"city": "Cambridge",
"feedback_thumbs_up_url": "<url-for-positive-feedback>",
"feedback_thumbs_down_url": "<url-for-negative-feedback>"
}
]
}
]
}
POST /ror/search_topkReturns at most K matches per affiliation, ranked by similarity score. This endpoint is the best fit for user-facing applications as it shows a fixed-size list of suggestions (e.g. a dropdown of top 3 candidates).
| Field | Type | Required | Description |
|---|---|---|---|
affiliations |
string[] |
Yes | One or more raw affiliation strings to search. |
top_k |
integer |
No | Maximum number of matches to return per affiliation (1-5). Defaults to 3 if omitted. A value outside 1-5 is rejected with 422 Unprocessable Entity. |
include_deprecated_ror_ids |
boolean |
No | Same as in /ror/search. |
curl -X POST "https://dev.mdpi.com/api/v1/ror/search_topk" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-api-key>" \
-d '{
"affiliations": ["Massachusetts Institute of Technology", "University of Cambridge"],
"top_k": 1
}'
{
"response": [
{
"raw_affiliation": "Massachusetts Institute of Technology",
"affiliation_matches": [
{
"institution_name": "Massachusetts Institute of Technology",
"institution_urls": ["https://web.mit.edu"],
"ror_id": "https://ror.org/042nb2s44",
"grid_id": "grid.116068.8",
"score": 0.98,
"country": "United States",
"country_code": "US",
"city": "Cambridge",
"feedback_thumbs_up_url": "<url-for-positive-feedback>",
"feedback_thumbs_down_url": "<url-for-negative-feedback>"
}
]
},
{
"raw_affiliation": "University of Cambridge",
"affiliation_matches": [
{
"institution_name": "University of Cambridge",
"institution_urls": ["https://www.cam.ac.uk"],
"ror_id": "https://ror.org/013meh722",
"grid_id": "grid.5335.0",
"score": 0.97,
"country": "United Kingdom",
"country_code": "GB",
"city": "Cambridge",
"feedback_thumbs_up_url": "<url-for-positive-feedback>",
"feedback_thumbs_down_url": "<url-for-negative-feedback>"
}
]
}
]
}
Both search endpoints return the same JSON format:
{
"response": [
{
"raw_affiliation": "string",
"affiliation_matches": [
/* Match Object, see below */
]
}
]
}
response contains one entry per affiliation string you sent.
| Field | Type | Description |
|---|---|---|
raw_affiliation |
string |
Echoes back the affiliation string exactly as submitted. |
affiliation_matches |
array or null |
Ranked list of candidate institutions. null when nothing cleared the confidence threshold. |
{
"response": [
{
"raw_affiliation": "Some Unrecognised Lab, Unknown City",
"affiliation_matches": null
}
]
}
Always check affiliation_matches for null before rendering a result list.
Each entry in affiliation_matches describes one candidate institution, sorted by score descending:
| Field | Type | Description |
|---|---|---|
institution_name |
string |
The canonical, official name of the institution from ROR. Use this as the primary display label. |
institution_urls |
string[] |
Official website URL(s) for the institution. Empty array if none listed. |
ror_id |
string |
The canonical ROR identifier URI, e.g. "https://ror.org/042nb2s44". |
grid_id |
string | null |
The legacy GRID identifier, if the institution has one. |
score |
float |
Confidence score in [0.0, 1.0]. Higher means a closer match - a natural fit for a confidence badge or sort key in the UI. |
country |
string |
Full country name, e.g. "Switzerland". |
country_code |
string |
ISO 3166-1 alpha-2 country code, e.g. "CH". |
city |
string |
City name from the ROR record. |
feedback_thumbs_up_url |
string |
Feedback URL for this specific match - see Sending feedback below. |
feedback_thumbs_down_url |
string |
Feedback URL for this specific match - see Sending feedback below. |
Each match includes a feedback_thumbs_up_url and a feedback_thumbs_down_url. Wire these up to a thumbs up/down control on each result row so users can tell us whether a match was correct.
POST URLs. Call them with an empty body, no JSON payload required.Authorization header - they work without authentication, so they're safe to call directly from frontend JavaScript.feedback_thumbs_up_url tells our system the user agreed with that match; calling feedback_thumbs_down_url tells it the user disagreed. This is inferred automatically from which URL was hit, there's nothing else to send.We recommend wiring up both buttons in the UI wherever matches are shown - the more feedback we get, the better future matches become.
# User clicks "thumbs up" on a result
curl -X POST "<feedback_thumbs_up_url from the response>"
| Status | Meaning | What to do |
|---|---|---|
200 OK |
Request succeeded. | Render response. |
401 Unauthorized |
Missing, malformed, or invalid API key. | Check the Authorization: Bearer <key> header; see Authentication. |
422 Unprocessable Entity |
Request body failed validation, e.g. top_k outside the 1-5 range, or a missing/malformed affiliations field. |
Fix the request body. Note this has a different detail shape than other errors - see below. |
429 Too Many Requests |
Daily quota exceeded for your API key. | Back off and retry after the daily reset, or request a higher-quota key. |
502 Bad Gateway |
The upstream matching service was unreachable or returned an unexpected response. | Transient, safe to retry with backoff. If it persists, contact the API team. |
Other 4xx/5xx |
Propagated as-is from the upstream service. | Treat as a failed request; the detail field in the JSON body has more context. |
Most error responses follow FastAPI's standard shape, where detail is a plain string:
{ "detail": "Request blocked, quota exceeded." }
Always branch on the HTTP status code first, then read detail for a user-facing or log message.
Every request to the API requires a registered API key (see Authentication). To get started, or if you need a higher, dedicated quota, e.g., for production use, load testing, or integration into another product, contact us to request one.
API keys are issued manually. To request one, contact us at: ai-team@mdpi.com
When reaching out, please include:
We'll get back to you with your key and its associated quota.
Once issued, send it as a bearer token on every request:
Authorization: Bearer <your-api-key>
See Authentication for full request examples, and keep the key server-side rather than embedding it in public frontend code.